我有一个数据框:
df <- data.frame(
Group=c('A','A','A','A','B','B','B','B'),
Activity = c('EOSP','NOR','EOSP','COSP','NOR','EOSP','WL','NOR'),
TimeLine=c(1,2,3,4,1,2,3,4)
)
我只想针对每个组 过滤两个活动,并按照我过滤的顺序进行过滤。例如,我只在搜索活动EOSP
和NOR
,但顺序也是如此。这段代码:
df %>% group_by(Group) %>%
filter(all(c('EOSP','NOR') %in% Activity) & Activity %in% c('EOSP','NOR'))
导致:
# A tibble: 6 x 3
# Groups: Group [2]
Group Activity TimeLine
<fct> <fct> <dbl>
1 A EOSP 1
2 A NOR 2
3 A EOSP 3
4 B NOR 1
5 B EOSP 2
6 B NOR 4
我不希望第3行,因为EOSP
在NOR
之后出现。同样,对于B组,我也不需要第4行,因为NOR
发生在EOSP
之前。我该如何实现?
答案 0 :(得分:3)
您可以使用match
获取Activity == EOSP
的第一个实例,并使用slice
删除之前的所有内容。完成此操作后,您就可以删除重复项并在EOSP
和NOR
(即
library(tidyverse)
df %>%
group_by(Group) %>%
mutate(new = match('EOSP', Activity)) %>%
slice(new:n()) %>%
distinct(Activity, .keep_all = TRUE) %>%
filter(Activity %in% c('EOSP', 'NOR'))
给出,
# A tibble: 4 x 4 # Groups: Group [2] Group Activity TimeLine new <fct> <fct> <dbl> <int> 1 A EOSP 1 1 2 A NOR 2 1 3 B EOSP 2 2 4 B NOR 4 2
注释1:您可以ungroup()
和select(-new)
注意2:此处发出警告消息
(警告消息: 1:在new:4L中:数值表达式包含4个元素:仅第一个使用 2:在new:4L中:数值表达式包含4个元素:仅第一个使用 )
不影响我们,因为我们都只需要第一个元素就可以使用
答案 1 :(得分:3)
这是data.table软件包的一个选项:您将df
与自身结合在一起,对其进行了子集化,仅保留EOSP
Activity
并计算TimeLine
的最小值按组划分,则只能保留TimeLine
大于或等于此TimeLine
的行,以确保仅在之前有NOR
时保留EOSP
。然后,如果每个组只保留2个活动,则删除重复的“组”和“活动”:
df[df[Activity=="EOSP", min(TimeLine), by=Group], on="Group"][Activity %in% c("NOR", "EOSP") & TimeLine >= V1][!duplicated(paste(Group, Activity))]
# Group Activity TimeLine V1
#1: A EOSP 1 1
#2: A NOR 2 1
#3: B EOSP 2 2
#4: B NOR 4 2
答案 2 :(得分:1)
这是一个dplyr
的想法:
df %>%
filter(Activity %in% c('EOSP','NOR')) %>%
group_by(Group) %>%
mutate(tmp = which(Activity == 'EOSP' & !duplicated(Activity))) %>%
filter(row_number() %in% c(tmp, tmp+1))
# A tibble: 4 x 4
# Groups: Group [2]
Group Activity TimeLine tmp
<fct> <fct> <dbl> <int>
1 A EOSP 1 1
2 A NOR 2 1
3 B EOSP 2 2
4 B NOR 4 2