yni*_*Sed 4 group-by r filter dplyr
我有一个数据框,看起来像这样:
Status ID
A 1
B 1
B 1
A 1
B 1
A 1
A 2
A 2
A 2
A 2
B 3
B 3
B 3
Run Code Online (Sandbox Code Playgroud)
为了说明我想要的输出,请看下面:
Status ID
B 1
B 1
B 1
A 2
A 2
A 2
A 2
B 3
B 3
B 3
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,唯一改变的是组ID = 1.如果一个组同时包含"A"和"B"状态,我想删除"A"状态.
但是,组ID 2和3没有更改(即没有删除行),因为:如果每个组ID仅包含"A",则它将保持不变.同样,如果每个组ID仅包含"B",它也将保持不变.因此两者保持不变.
使用dplyr,这是我的尝试:
library(dplyr)
df1_clean <- df1 %>% group_by(ID, Status)
%>% filter(ifelse((Status == A | Status == B), Status == B,
ifelse((Status == A), Status == A,
ifelse((Status == B), Status == B))))
Run Code Online (Sandbox Code Playgroud)
但是,此过滤器不起作用.任何帮助,将不胜感激!
我们可以使用filter分组ID
library(dplyr)
df %>%
group_by(ID) %>%
filter(all(Status == "A") | all(Status == "B") | Status == "B")
# Status ID
# <fct> <int>
# 1 B 1
# 2 B 1
# 3 B 1
# 4 A 2
# 5 A 2
# 6 A 2
# 7 A 2
# 8 B 3
# 9 B 3
#10 B 3
Run Code Online (Sandbox Code Playgroud)
我们也可以使用 n_distinct
df %>%
group_by(ID) %>%
filter(n_distinct(Status) == 1 | Status == "B")
Run Code Online (Sandbox Code Playgroud)
等价的基础R ave版本将是
df[as.logical(with(df, ave(Status, ID, FUN = function(x)
all(x == "A") | all(x == "B") | x == "B"))), ]
df[as.logical(with(df, ave(Status, ID, FUN = function(x)
length(unique(x)) == 1 | x == "B"))), ]
Run Code Online (Sandbox Code Playgroud)
小智 5
首先,始终建议以复制友好格式提供示例,dput(df1)以便其他人可以轻松地重新生成数据.
这个任务可以通过创建一个标志列来实现,该标志列指示a ID是否有多个Status,然后过滤那些没有多个status或有多个的那个status == "B".如下:
clean_df1 <- df1 %>%
group_by(ID) %>%
mutate(multiple = if_else(n_distinct(Status) > 1, TRUE, FALSE)) %>%
filter(!multiple | Status == "B") %>%
ungroup() %>% select(- multiple)
# A tibble: 10 x 2
Status ID
<fct> <dbl>
1 B 1
2 B 1
3 B 1
4 A 2
5 A 2
6 A 2
7 A 2
8 B 3
9 B 3
10 B 3
Run Code Online (Sandbox Code Playgroud)