给定组中至少包含一个非NA值,请删除组中具有NA的行

Vee*_*kar 5 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")
Run Code Online (Sandbox Code Playgroud)

看起来像

   class value
1 orange    NA
2  apple    NA
3  apple     1
4  grape     1
5  berry    NA
Run Code Online (Sandbox Code Playgroud)

仅当组具有另一个非NA值时,如何删除组中具有NA的行

期望的输出

   class value
1 orange    NA
2  apple     1
3  grape     1
4  berry    NA
Run Code Online (Sandbox Code Playgroud)

这可以通过使用子集和合并的三个步骤来完成。我对一种data.table方法感兴趣

Fel*_*ard 6

尝试dplyr。即使对于大型数据帧,它也可以产生更简单的代码并且运行速度非常

df %>%
    group_by(class) %>%
    filter(!(is.na(value) & sum(!is.na(value)) > 0)) %>%
    ungroup
Run Code Online (Sandbox Code Playgroud)

最后的取消分组位只是为了使您最终不会获得分组的数据帧(实际上是dplyr :: tbl)。


akr*_*run 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
Run Code Online (Sandbox Code Playgroud)

或者我们可以通过稍微修改条件来将条件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
Run Code Online (Sandbox Code Playgroud)

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

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