dplyr将“尾巴”行折叠成更大的组

时间:2018-11-10 15:16:45

标签: r dplyr

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

[编辑]-我修复了示例数据。抱歉。

3 个答案:

答案 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)

这是一种为您提供所需组名称的方法,您无需事先考虑所需的情况(例如,它将创建resultgrp3 ,...取决于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