删除R

时间:2017-03-24 20:22:15

标签: r dataframe

我的数据集类似于下面的数据集:

d <- data.frame(A=c(11,11,11,11,21,21,111,111,111,44,44,44),
                B=c(0,1,0,0,0,0,1,0,0,0,0,0),
                C=c(3,2,1,3,4,2,1,2,3,12,22,31))
d
      A B  C
 1   11 0  3
 2   11 1  2
 3   11 0  1
 4   11 0  3
 5   21 0  4
 6   21 0  2
 7  111 1  1
 8  111 0  2
 9  111 0  3
10   44 0 12
11   44 0 22
12   44 0 31

我想删除唯一A中每行B = 0的行。例如,当A = 11时,有B = 1(第2行),所以没关系。相比之下,对于A = 21,所有B都等于零,所以我想删除A = 21的所有行。对于A = 44,所有B都是零,所以我想删除A = 44的所有行。

最后,我需要获取此数据框:

new_d
    A B  C
1  11 0  3
2  11 1  2
3  11 0  1
4  11 0  3
5 111 1 12
6 111 0 22
7 111 0 31

P.S。不关心C列,我添加它只是为了表明数据集中有超过2列。

3 个答案:

答案 0 :(得分:2)

您可以使用ave和逻辑子集,如下所示:

d[!!ave(d$B, d$A, FUN=function(i) !all(i == 0)),]
    A B C
1  11 0 3
2  11 1 2
3  11 0 1
4  11 0 3
7 111 1 1
8 111 0 2
9 111 0 3

这里,当向量包含非零元素时,!all(i == 0)返回TRUE。 ave对每个组执行此检查,并返回与初始向量大小相同的向量,!!将其转换为逻辑向量。此转换是必要的,因为ave将返回与初始向量相同类型的向量。比!!更明确的是as.logical

d[as.logical(ave(d$B, d$A, FUN=function(i) !all(i == 0))),]

答案 1 :(得分:2)

或使用简单的dplyr操作:(顺便说一句,我相信您的预期输出已关闭)

require(dpylr)
d %>% group_by(A) %>% filter(sum(B) >= 1)

答案 2 :(得分:2)

base R解决方案如何:

d[d$A %in% d$A[d$B!=0], ]

它也很快:

library(microbenchmark)
library(dplyr)

set.seed(33)  ## making a larger example
A <- do.call(c, lapply(sample(10000, 2000), function(x) rep(x, sample(100, 1))))
B <- sample(c(0,1), length(A), replace = TRUE, prob = c(18/19, 1/19))
C <- sample(10^5, length(A), replace = TRUE)
df <- data.frame(A, B, C)

superBase <- function(d) {d[d$A %in% d$A[d$B!=0], ]}
  aveStat <- function(d) {d[!!ave(d$B, d$A, FUN=function(i) !all(i == 0)),]}
 dplyrSol <- function(d) {d %>% group_by(A) %>% filter(sum(B) >= 1)}

microbenchmark(superBase(df), aveStat(df), dplyrSol(df))
Unit: milliseconds
         expr      min       lq     mean   median       uq      max neval cld
superBase(df) 21.44030 23.81434 30.00466 26.67157 27.32492 167.1614   100 a  
  aveStat(df) 34.23338 39.03278 49.12483 40.29534 42.96865 204.0808   100  b 
 dplyrSol(df) 63.52571 65.32626 71.64950 67.20563 69.43784 215.5980   100   c

给出相同的结果:

identical(superBase(df), aveStat(df))
[1] TRUE