R: удалить несколько строк на основе пропущенных значений в меньшем количестве строк - PullRequest
0 голосов
/ 28 марта 2012

У меня есть фрейм данных R с данными от нескольких субъектов, каждый из которых проверен несколько раз.Для выполнения статистики на множестве есть фактор для субъекта («id») и строка для каждого наблюдения (заданная фактором «session»).Т.е.

print(allData)
id     session     measure
1      1           7.6
2      1           4.5
3      1           5.5
1      2           7.1
2      2           NA
3      2           4.9

В вышеприведенном примере есть простой способ удалить все строки с id == 2, учитывая, что столбец "measure" содержит NA в одной из строк, где id == 2?

В более общем смысле, поскольку у меня действительно много мер (столбцов) и четырех сессий (строк) для каждого предмета, существует ли элегантный способ удалить все строки с заданным уровнем фактора «id»,учитывая, что (хотя бы) одна из строк с этим уровнем «id» содержит NA в столбце?

У меня есть интуиция, что может быть встроенная функция, которая могла бы решить эту проблему более элегантно, чеммое текущее решение:

# Which columns to check for NA's in
probeColumns = c('measure1','measure4') # Etc...

# A vector which contains all levels of "id" that are present in rows with NA's in the probeColumns
idsWithNAs = allData[complete.cases(allData[probeColumns])==FALSE,"id"]

# All rows that isn't in idsWithNAs
cleanedData = allData[!allData$id %in% idsWithNAs,]

Спасибо, / Jonas

Ответы [ 2 ]

3 голосов
/ 29 марта 2012

Вы можете использовать функцию ddply из пакета plyr до 1) поднабор ваших данных на id, 2) примените функцию, которая будет возвращать NULL, если вложенный data.frame содержит NA в выбранных вами столбцах, или сам data.frame в противном случае, и 3) объединить все обратно в data.frame.

allData <- data.frame(id       = rep(1:4, 3),
                      session  = rep(1:3, each = 4),
                      measure1 = sample(c(NA, 1:11)),
                      measure2 = sample(c(NA, 1:11)),
                      measure3 = sample(c(NA, 1:11)),
                      measure4 = sample(c(NA, 1:11)))
allData                      
#    id session measure1 measure2 measure3 measure4
# 1   1       1        3        7       10        6
# 2   2       1        4        4        9        9
# 3   3       1        6        6        7       10
# 4   4       1        1        5        2        3
# 5   1       2       NA       NA        5       11
# 6   2       2        7       10        6        5
# 7   3       2        9        8        4        2
# 8   4       2        2        9        1        7
# 9   1       3        5        1        3        8
# 10  2       3        8        3        8        1
# 11  3       3       11       11       11        4
# 12  4       3       10        2       NA       NA

# Which columns to check for NA's in
probeColumns = c('measure1','measure4')

library(plyr)
ddply(allData, "id",
      function(df)if(any(is.na(df[, probeColumns]))) NULL else df)
#   id session measure1 measure2 measure3 measure4
# 1  2       1        4        4        9        9
# 2  2       2        7       10        6        5
# 3  2       3        8        3        8        1
# 4  3       1        6        6        7       10
# 5  3       2        9        8        4        2
# 6  3       3       11       11       11        4
0 голосов
/ 28 марта 2012

Используя ваш пример, две последние команды могут быть преобразованы в такую ​​строку. Он должен дать тот же результат, и выглядит проще.

cleanedData <- allData[complete.cases(allData[,probeColumns]),]

Это правильная версия, которая использует только базовый пакет. Просто для удовольствия. :) Но это не компактно и не просто. Ответ Флоделя аккуратнее. Даже ваше первоначальное решение более компактно, и я думаю быстрее.

cleanedData <- do.call(rbind, sapply(unique(allData[,"id"]), function(x) {if(all(!is.na(allData[allData$id==x, probeColumn]))) allData[allData$id==x,]}))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...