首先,请告诉我是否我的dplyr使用不佳,因为我不确定我是否以最佳方式处理这个问题。我有下面的数据框:
mydf = data.frame(user = c(7,7,7,7,7,7,7,8,8,8,8,8,8),
col1 = c('0','0','1','1','0','3','NULL','3','3','0','1','0','0'),
col2 = runif(n=13),
col3 = letters[1:13],
stringsAsFactors = FALSE)
> mydf
user col1 col2 col3
1 7 0 0.7607907 a
2 7 0 0.1580448 b
3 7 1 0.8063540 c
4 7 1 0.7331512 d
5 7 0 0.2433631 e
6 7 3 0.2357065 f
7 7 NULL 0.4864172 g
8 8 3 0.6806089 h
9 8 3 0.2229874 i
10 8 0 0.6187911 j
11 8 1 0.7617177 k
12 8 0 0.5884821 l
13 8 0 0.4985750 m
我想要做的过滤有些冗长,但我会尝试 - 我想通过删除所有 col1 == '0' 为行来过滤数据框,如果该行出现在该用户的第一个 col1 == '1' 之后。(粗体表示我弄错了原问题,颠倒了0和1)。
例如,对于用户7,第3行具有 col1 == '1',因此我想过滤所有在第3行之后且 col1 == '0' 的行(在本例中仅为第5行)。然后,对于用户8,第11行是该用户的第一行,其中 col1 == '1',因此我想过滤行12和13,因为 col1 == '0'。
我的最终输出应该类似于这样:
> mydf
user col1 col2 col3
1 7 0 0.7607907 a
2 7 0 0.1580448 b
3 7 1 0.8063540 c
4 7 1 0.7331512 d
6 7 3 0.2357065 f
7 7 NULL 0.4864172 g
8 8 3 0.6806089 h
9 8 3 0.2229874 i
10 8 0 0.6187911 j
11 8 1 0.7617177 k
我尝试了以下方法,但它没有奏效。我认为添加一个rownums列,然后按用户分组,再按照我描述的方式进行筛选会起作用。我的想法是我的filter调用存在问题:
mydf %>%
mutate(rownums = 1:nrow(mydf)) %>%
group_by(user) %>%
filter(!(col1 == "0" & rownums > min(which(col1 == "1"))))
# A tibble: 9 x 5
# Groups: col0 [2]
user col1 col2 col3 rownums
<dbl> <chr> <dbl> <chr> <int>
1 7 0 0.2088034 a 1
2 7 0 0.2081894 b 2
3 7 1 0.1825428 c 3
4 7 1 0.2143353 d 4
5 7 3 0.1979774 f 6
6 7 NULL 0.2990799 g 7
7 8 3 0.7808038 h 8
8 8 3 0.1694272 i 9
9 8 1 0.1526450 k 11
这个输出和正确的输出的区别在于,这个输出错误地过滤了原始数据框的第10行。如有帮助,请指教!编辑 - 我特别想知道在使用dplyr时,group_by() %>% filter()是否是不好的做法。我的99% group_by()都跟着summarize(),这显然更有意义。编辑2 - 我想我搞定了!
mydf %>%
group_by(col0) %>%
mutate(rownums = 1:length(col0)) %>%
filter(!(col1 == "0" & rownums > min(which(col1 == "1"))))
简单地反转mutate()和group_by()的调用顺序,并稍微调整mutate()的调用,看起来已经完成了。但我很乐意听取更好的方法。