library(tidyverse)
df <- tibble(a = as.factor(1:20), b = c(50, 20, 13, rep(2, 10), rep(1, 7)))
如何使dplyr查看此数据帧df
并将2
的所有这些出现折叠为一个求和的组,并将1
的所有这些出现折叠为一个求和的组?并保留其余数据框。
打开它:
# A tibble: 20 x 2
a b
<fct> <dbl>
1 1 50
2 2 20
3 3 13
4 4 2
5 5 2
6 6 2
7 7 2
8 8 2
9 9 2
10 10 2
11 11 2
12 12 2
13 13 2
14 14 1
15 15 1
16 16 1
17 17 1
18 18 1
19 19 1
20 20 1
对此:
# A tibble: 5 x 2
a b
<fct> <dbl>
1 1 50
2 2 20
3 3 13
4 grp2 20
5 grp1 7
[编辑]-我修复了示例数据。抱歉。
答案 0 :(得分:2)
我们按制造的sortkey
分组以保持排序顺序。我们使用了一个事实,即b
在输入中按降序排列,但是如果实际数据中不是这种情况,则将sortkey = -b
替换为更通用的sortkey = data.table::rleid(b)
或更长的{{1 }}。
我们还将sortkey = cumsum(coalesce(b != lag(b), FALSE))
转换为组名,以提供新的b
。尚不清楚要将哪些组转换为grp ...形式。硬编码1和2?有不止一排的团体吗?组末尾有多行?无论如何,只要弄清a
中的条件,就很容易了。
最后执行求和,然后删除if_else
。
sortkey
给予:
df %>%
group_by(sortkey = -b, a = paste0(if_else(b %in% 1:2, "grp", ""), b)) %>%
summarize(b = sum(b)) %>%
ungroup %>%
select(-sortkey)
答案 1 :(得分:1)
这是一种方法。我已经将a
从要素转换为字符,使事情变得更容易。您可以根据需要将其转换回因子。另外,您的测试数据有误。
df <- tibble(a = as.character(1:20), b = c(50, 20, 13, rep(2, 10), rep(1, 7)))
df %>%
mutate(
a = case_when(
b == 1 ~ "grp1",
b == 2 ~ "grp2",
TRUE ~ a
)
) %>%
group_by(a) %>%
summarise(b = sum(b))
# A tibble: 5 x 2
a b
<chr> <dbl>
1 1 50
2 2 20
3 3 13
4 grp1 7
5 grp2 20
答案 2 :(得分:1)
这是一种为您提供所需组名称的方法,您无需事先考虑所需的情况(例如,它将创建result
,grp3
,...取决于grp4
中的数字)。
b
输出:
library(dplyr)
df %>%
mutate(
grp = as.numeric(lag(df$b) != df$b),
grp = cumsum(ifelse(is.na(grp), 0, grp))
) %>% group_by(grp) %>%
mutate(
a = ifelse(n() > 1, paste0("grp", b), a),
b = sum(b)
) %>% ungroup() %>% distinct(a, b)
请注意,代码也可以压缩,但在我看来会导致一定程度的可读性:
a b
<chr> <dbl>
1 1 50
2 2 20
3 3 13
4 grp2 20
5 grp1 7