Создание нового столбца, информирующего о том, сколько уникальных значений содержится в нескольких столбцах

#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 должно лучше отражать количество изменений в школе, где a 0 указывает, что был только один школьный идентификатор. Это означает, что название столбца, безусловно, вводит в заблуждение, этого не должно быть - 1L , если мы назовем его таковым. Но редактирование для $schools_changes должно лучше отражать то, что вы сказали, что вам нужно.

3. Вы правы, спасибо за экскурсию, schools_changes-это именно то, что мне нужно!