假设该组包含至少一个非 NA 值,则删除组中具有 NA 的行
Remove rows with NA in a group, given the group contains at-least one non NA value
样本数据
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
方法感兴趣
我们可以使用 data.table
。将 'data.frame' 转换为 'data.table' (setDT(df)
)。按 'class' 分组,我们使用 if/else
条件检查 'value' 和 .SD
子集中 'NA' 元素的出现情况
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]
您可以为所有带有 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)
尝试dplyr
。它生成更简单的代码并且非常快,即使对于大型数据帧也是如此:
df %>%
group_by(class) %>%
filter(!(is.na(value) & sum(!is.na(value)) > 0)) %>%
ungroup
末尾的取消分组位只是为了让您不会得到分组的数据帧(实际上是 dplyr::tbl)。
这是一种不同的 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
以获取详细信息。
样本数据
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
方法感兴趣
我们可以使用 data.table
。将 'data.frame' 转换为 'data.table' (setDT(df)
)。按 'class' 分组,我们使用 if/else
条件检查 'value' 和 .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]
您可以为所有带有 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)
尝试dplyr
。它生成更简单的代码并且非常快,即使对于大型数据帧也是如此:
df %>%
group_by(class) %>%
filter(!(is.na(value) & sum(!is.na(value)) > 0)) %>%
ungroup
末尾的取消分组位只是为了让您不会得到分组的数据帧(实际上是 dplyr::tbl)。
这是一种不同的 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
以获取详细信息。