2012-03-28 114 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