如何删除具有NA的行和遵循NA的行?

时间:2016-12-19 12:52:17

标签: r conditional na

我有一些数据,我希望通过因子级别删除NA和NAs之后的数据。

删除NA非常简单:

df <- data.frame(a=c("A","A","A","B","B","B","C","C","C","D","D","D"), b=c(0,1,0,0,0,0,0,1,0,0,0,1) ,c=c(4,5,3,2,1,5,NA,5,1,6,NA,2))
df
newdf<-df[complete.cases(df),];newdf

最终结果应该删除C的所有行和最后两行D.

希望你能提供帮助。

3 个答案:

答案 0 :(得分:4)

我们可以尝试使用data.table。转换&#39; data.frame&#39;到&#39; data.table&#39; (setDT(df)),按&#39; a&#39;,得到&#39; c&#39;中的NA元素的逻辑向量的累积和。并检查它是否小于1到子集

library(data.table)
setDT(df)[,  .SD[cumsum(is.na(c))<1], by= a]

或者.I的更快选项,可以返回逻辑向量的行索引并对行进行子集化。

setDT(df)[df[, .I[cumsum(is.na(c)) < 1], by = a]$V1]
#   a b c
#1: A 0 4
#2: A 1 5
#3: A 0 3
#4: B 0 2
#5: B 0 1
#6: B 0 5
#7: D 0 6

答案 1 :(得分:3)

dplyr中的类似解决方案是

library(dplyr)
df %>% group_by(a) %>% filter(!is.na(cumsum(c)))

输出:

Source: local data frame [7 x 3]
Groups: a [3]

       a     b     c
  <fctr> <dbl> <dbl>
1      A     0     4
2      A     1     5
3      A     0     3
4      B     0     2
5      B     0     1
6      B     0     5
7      D     0     6

如果我们采用变量C的累积和,则第一个NA之后的任何值都将转换为NA。在组级别执行此操作允许我们删除NA行并获得所需的输出。

答案 2 :(得分:3)

基础R中的经典split-apply-combine:

do.call(rbind,lapply(split(df, df$a),function(x)x[cumsum(is.na(x$c))<1,]))

这又是一次,但有几行:

split_df <- split(df, df$a)
apply_df <- lapply(split_df, function(x)x[cumsum(is.na(x$c))<1,])
combine_df <- do.call(rbind, apply_df)

结果:

> do.call(rbind,lapply(split(df, df$a),function(x)x[cumsum(is.na(x$c))<1,]))
#    a b c
#A.1 A 0 4
#A.2 A 1 5
#A.3 A 0 3
#B.4 B 0 2
#B.5 B 0 1
#B.6 B 0 5
#D   D 0 6