2012-03-28 86 views
0

我有一个来自多个主题的数据的R数据框,每个主题都测试了几次。要对集合进行统计,主题(“id”)和每个观察的行(由“会话”因子给出)都有一个因子。即R:根据更少行中的缺失值删除多行

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中的所有行,鉴于“测量”列包含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,] 

谢谢, /乔纳斯

+0

可能有一种方法可以用'sqldf'来实现,但我认为它从根本上不会更简单。 – 2012-03-28 12:14:36

回答

3

可以使用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

谢谢,flodel!我认为ddply解决方案的真正价值在于它比我上面的自制解决方案更加灵活。如果我需要的话,我可以简单地将更多的条件和操作添加到函数中。 – 2012-04-17 07:03:40

0

使用你的例子最后两它的命令可以在这样的字符串中转换。它应该产生相同的结果,看起来更简单。

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

这是一个只使用基础包的正确版本。只是为了好玩。 :)但它既不紧凑也不简单。 flodel的答案很整洁。即使你最初的解决方案更紧凑,我认为更快。

cleanedData <- do.call(rbind, sapply(unique(allData[,"id"]), function(x) {if(all(!is.na(allData[allData$id==x, probeColumn]))) allData[allData$id==x,]})) 
+0

谢谢。但是,您的提案只会删除其中包含NA的行(上例中的第5行)。我正在寻找一个解决方案,删除第2行,因为它具有与第5行相同的“id”级别。 – 2012-03-28 13:14:37

+0

@Jonas,对不起,我不明白你到底想要什么。我会添加另一个答案,只是为了好玩,它使用了基本包。但是flodel的答案更加紧凑和美观。 – DrDom 2012-03-29 05:25:53