#r
#r
Вопрос:
Итак, у меня есть фрейм данных, который выглядит примерно так, но с 10 тысячами строк:
студентИД | school_ID_1 | school_ID_2 | school_ID_3 | school_ID_4 |
---|---|---|---|---|
5555 | 3321 | 3311 | 3311 | 3311 |
5544 | 3347 | 3326 | 3350 | 3347 |
5533 | 3364 | 3314 | 3328 | 3302 |
5566 | 3389 | 3351 | 3379 | 3384 |
5577 | 3312 | 3303 | 3320 | 3320 |
Если бы в моих данных был только один студент, используя следующую команду:
dep_edu2016_4x = data.frame(table(unlist(dep_edu2016_4x)))
Сказал бы мне, сколько раз этот ученик менял школу за год, по количеству строк, которые вернет таблица, за вычетом строки StudentID. Я уже сделал манекен, чтобы узнать, сменили ли они школу, теперь мне нужно решение для создания новой колонки, сообщающей мне, сколько раз каждый ученик менял школу
Ответ №1:
dep_edu2016_4x$unique_schools lt;- apply( subset(dep_edu2016_4x, select = school_ID_1:school_ID_4), 1, function(z) length(unique(z)) - 1L) dep_edu2016_4x # studentID school_ID_1 school_ID_2 school_ID_3 school_ID_4 unique_schools # 1 5555 3321 3311 3311 3311 1 # 2 5544 3347 3326 3350 3347 2 # 3 5533 3364 3314 3328 3302 3 # 4 5566 3389 3351 3379 3384 3 # 5 5577 3312 3303 3320 3320 2
Проходной:
subset(...)
это один из способов, чтобы извлечь только столбцы нам нужны, в том числе ряд колонн; мы легко могли бы начать сdep_edu2016_4x[,-1]
того, чтобы выделить все, за исключениемstudentID
, но (1) я не полагаю никаких других столбцов; и даже если это весь ваш набор данных, а затем (2) еще добавим, что столбец, мы не можем рассчитать ее без смещения это тем, что дополнительный столбец.apply(X, MARGIN, FUN)
работает с каждой строкой (MARGIN=1
) набора данных (X=x
) и применяет функцию (FUN
) к этим данным. В этом случае для каждой строки он возвращает одно целое число.length(unique(z)) - 1L
вычисляет количество различных школ минус 1, что является хорошим показателем для количества изменений.
Однако подсчет школьных изменений немного неверен: если ученик начинает учиться в школе 3321
, переходит в 3311
, затем возвращается в 3321
, то length(unique(.))-1L
это не сработает. (Похоже, это относится и к студентам 5544
.) Нам понадобится что-то более надежное, если вы хотите защититься от этого:
changes lt;- function(z) if (length(z)) sum(z[-1] != z[-length(z)]) else 0L dep_edu2016_4x$schools_changes lt;- apply(subset(dep_edu2016_4x, select = school_ID_1:school_ID_4), 1, changes) dep_edu2016_4x # studentID school_ID_1 school_ID_2 school_ID_3 school_ID_4 unique_schools schools_changes # 1 5555 3321 3311 3311 3311 1 1 # 2 5544 3347 3326 3350 3347 2 3 # 3 5533 3364 3314 3328 3302 3 3 # 4 5566 3389 3351 3379 3384 3 3 # 5 5577 3312 3303 3320 3320 2 2
Комментарии:
1. Тх! Это решает проблему, но в этом случае мне не нужно было бы удалять 1, потому что выбранные столбцы исключают идентификатор студента.
2. Я думаю, вы неправильно поняли, см. мою недавнюю правку. Это
- 1L
должно лучше отражать количество изменений в школе, где a0
указывает, что был только один школьный идентификатор. Это означает, что название столбца, безусловно, вводит в заблуждение, этого не должно быть- 1L
, если мы назовем его таковым. Но редактирование для$schools_changes
должно лучше отражать то, что вы сказали, что вам нужно.3. Вы правы, спасибо за экскурсию, schools_changes-это именно то, что мне нужно!