Подсчет NA в части строки в data.table - PullRequest
0 голосов
/ 26 сентября 2018

У меня есть набор данных df, структура которого похожа на приведенный ниже пример:

nr countrycode questionA questionB questionC WeightquestionA WeightquestionB WeightquestionC
1  NLD               2         1         4         0.6             0.2             0.2
2  NLD               NA        4         NA        0.4             0.4             0.2
3  NLD               4         4         1         0.2             0.2             0.6
4  BLG               1         NA        1         0.1             0.5             0.4
5  BLG               5         3         5         0.2             0.2             0.6

Вопросы A, B и C относятся к аналогичной теме, и в результате я хотел бысоздайте средний балл по всем вопросам с учетом важности каждого вопроса (WeightquestionA WeightquestionB WeightquestionC).

В настоящее время я вручную рассчитал средний балл.

(questionA*WeightquestionA) + (questionB*WeightquestionB) + (questionC*WeightquestionC)

Это не было бы непреодолимой проблемой, если бы не АН (для которых: нет, они не могут быть удалены).В результате я хотел бы автоматизировать процесс.

В настоящее время я думаю об использовании sum(!is.na()) для подсчета не-NA в каждом вопросе (A, B, C) для каждой строки (с 1 по 5)и поместив это значение в новый столбец.

С data.table у меня всегда возникают проблемы с правильным синтаксисом.Я считаю, что это должно быть что-то вроде:

df[, NonNA:=sum(!is.na(questionA + questionB + questionC))]

Но это суммирует все NA в столбце, а не для каждой строки.Как мне написать синтаксис для расчета для строки?

Я хотел бы ссылаться на столбцы отдельно по имени, потому что они не находятся рядом друг с другом в фактическом df.

Желаемый вывод:

nr countrycode qA qB qC WeightquestionA WeightquestionB WeightquestionC NonNA
1  NLD         2  1  4         0.6             0.2             0.2      3
2  NLD         NA 4  NA        0.4             0.4             0.2      1
3  NLD         4  4  1         0.2             0.2             0.6      3
4  BLG         1  NA 1         0.1             0.5             0.4      2
5  BLG         5  3  5         0.2             0.2             0.6      3

Ответы [ 3 ]

0 голосов
/ 26 сентября 2018

Используя data.table, вы можете сделать это:

df[, NonNA := sum(!is.na(questionA), !is.na(questionB), !is.na(questionC)), by = .(nr)]

Базовое решение:

df$nonNA <- rowSums(!is.na(df[,c("questionA", "questionB", "questionC")]))
0 голосов
/ 26 сентября 2018

Другая альтернатива с рекомендацией от snoram:

df[, NonNA := rowSums(!is.na(.SD)), 
    .SDcols=paste0("question", LETTERS[1:3])]

А также:

df[, NonNA := Reduce(function(x, y) x + !is.na(y), .SD, init=rep(0L, .N)), 
    .SDcols=paste0("question", LETTERS[1:3])]
0 голосов
/ 26 сентября 2018

Мы можем считать не NA (для столбца questionA, questionB и questionC, т. Е. Столбца с 3 по 5), используя apply, как показано ниже:

df$nonNA=apply(df[,3:5], 1, function(x) length(which(!is.na(x))))

или (предложение от snoarm)

df$nonNA=apply(df[,3:5], 1, function(x) sum(!is.na(x)))

Пример вывода:

   questionA questionB questionC nonNA
1         2         1         4     3
2        NA         4        NA     1
3         4         4         1     3
4         1        NA         1     2
5         5         3         5     3
...