如果组包含至少一个非NA值,则删除组中包含NA的行

时间:2015-07-16 19:31:02

标签: r data.table

示例数据

df = structure(list(class = structure(c(4L, 1L, 1L, 3L, 2L), .Label = c("apple", 
"berry", "grape", "orange"), class = "factor"), value = c(NA, 
NA, 1, 1, NA)), .Names = c("class", "value"), row.names = c(NA, 
-5L), class = "data.frame")

看起来像

   class value
1 orange    NA
2  apple    NA
3  apple     1
4  grape     1
5  berry    NA

仅当组具有另一个非NA值

时,如何在组中删除具有NA的行

期望的输出

   class value
1 orange    NA
2  apple     1
3  grape     1
4  berry    NA

使用子集和合并可以分三步完成。我对data.table方法感兴趣

4 个答案:

答案 0 :(得分:5)

试试dplyr。它产生更简单的代码并且非常快,即使对于大型数据帧也是如此:

df %>%
    group_by(class) %>%
    filter(!(is.na(value) & sum(!is.na(value)) > 0)) %>%
    ungroup

最后的ungroup位只是为了不使用分组数据帧(实际上是dplyr :: tbl)。

答案 1 :(得分:2)

我们可以使用data.table。转换' data.frame'到' data.table' (setDT(df))。按照'类'分组,我们检查if/else条件是否发生了' NA'价值中的元素'和.SD

的子集
library(data.table)
setDT(df)[, if(any(!is.na(value))) .SD[!is.na(value)] else .SD , by = class]
#    class value
#1: orange    NA
#2:  apple     1
#3:  grape     1
#4:  berry    NA

或者我们可以通过略微修改条件将条件从any更改为all

setDT(df)[, if(all(is.na(value))) .SD else .SD[!is.na(value)], by = class]
#    class value
#1: orange    NA
#2:  apple     1
#3:  grape     1
#4:  berry    NA

或者我们得到行索引(.I),然后对数据集进行子集化。

indx <- setDT(df)[, if(any(!is.na(value))) .I[!is.na(value)] else .I, class]$V1
df[indx]

答案 2 :(得分:2)

这是一种不同的data.table方法:

setkey(df,class)
df[!is.na(value)][J(unique(df$class))]

#     class value
# 1:  apple     1
# 2:  berry    NA
# 3:  grape     1
# 4: orange    NA

这要归功于默认操作nomatch=NA。在控制台中输入?data.table以获取详细信息。

答案 3 :(得分:1)

您可以使用NA创建所有类的临时变量,然后取出所有NA并添加任何完全删除的类。

df<-setDT(df)
temp<-df[is.na(value),list(class=unique(class), value)]
df<-df[!is.na(value)]
df<-rbindlist(list(df, temp[!class %in% df[,class]]))
rm(temp)