根据条件汇总行

时间:2018-03-10 10:54:08

标签: r dplyr

创建样本数据集以重现问题

library(dplyr)
x <- c('MS','Google','MS','FB','Amazon','Google','IBM','IBM','IBM','MS')
item <- as.data.frame(x,stringsAsFactors = F)
data <- item %>% group_by(x) %>% summarise(n = n())

# A tibble: 5 x 2
  x          n
  <chr>  <int>
1 Amazon     1
2 FB         1
3 Google     2
4 IBM        3
5 MS         3

现在我打算创建一个数据集,其中所有'n'计数小于2应该在一行中总结为'other',同时它也将n计数总和为

x          n
  <chr>  <int>
1 Other      2
2 Google     2
3 IBM        3
4 MS         3

我可以通过下面提到的代码来实现它,但我确定这不是很好的方法,如果我可以通过dplyr查询直接做同样的建议我

data$x[data$n < 2]= 'Other'
data <- aggregate(n~x, data, FUN = sum)

3 个答案:

答案 0 :(得分:4)

以下是dplyr

的想法
library(dplyr)

data %>% 
 mutate(grp = cumsum(c(1, diff(n < 2) != 0)), 
        grp = replace(grp, n >=2, grp[n >= 2] + row_number()[n >= 2])) %>%
 group_by(grp) %>% 
 summarise(x = toString(x), n = sum(n)) %>% 
 ungroup() %>% 
 select(-grp)

给出,

# A tibble: 4 x 2
  x              n
  <chr>      <int>
1 Amazon, FB     2
2 Google         2
3 IBM            3
4 MS             3

注意:如果您真的想使用Other,那么在管道的末尾添加以下内容,

... %>% mutate(x = replace(x, grepl(',', x), 'Other'))

解读&#39;分组的cumsum部分可以将其分解。

我们希望创建一个组,其中该组中的所有值都小于2.但是,我们也不可避免地为大于(或等于)2的值创建组。为了避免汇总这些组,我们通过添加来替换它们它们的增量值。这将确保值大于2的组只有一个元素,从而确保它们不会在最后得到汇总。 获取组的技巧是创建一个值小于2的逻辑向量,并使用差异来查找何时从TRUE变为FALSE(因此...!= 0部分)。由于diff会删除某个值,因此我们会c(1, diff(...))手动添加它。请注意,您可以放置​​TRUE而不是1。 cumsum然后创建组。为了避免总结具有值> gt的组。 2,我们通过将row_number添加到它们来替换它们。为什么row_number?因为它增加,从而使所有群体都独一无二。

x <- c(1, 1, 3, 4, 2, 1, 1, 1, 5)

x < 2
#[1]  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE FALSE
diff(x < 2) != 0
#[1] FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE
cumsum(c(1, diff(x < 2) != 0))
#[1] 1 1 2 2 2 3 3 3 4

答案 1 :(得分:2)

我们还可以在case_when中使用group_by来更改&#39; x&#39;价值与其他&#39;在哪里&#39; n&#39;是1然后执行sum的&#39; n&#39;在summarise

library(dplyr)
data %>% 
   group_by(x = case_when(n ==1 ~ 'Other', 
                              TRUE ~ x)) %>% 
   summarise(n = sum(n))
# A tibble: 4 x 2
#  x          n
#   <chr>  <int>
#1 Google     2
#2 IBM        3
#3 MS         3
#4 Other      2

答案 2 :(得分:1)

使用bind_rowsfilter作为另一种选择:

library(dplyr)
x <- c('MS','Google','MS','FB','Amazon','Google','IBM','IBM','IBM','MS')
item <- as.data.frame(x,stringsAsFactors = F)
data <- item %>% group_by(x) %>% summarise(n = n())

data %>% {
  bind_rows(filter(., n >= 2), 
            filter(., n < 2) %>% summarise(x = "Other",  n = sum(n))
            )

}

#  x          n
#  <chr>  <int>
#1 Google     2
#2 IBM        3
#3 MS         3
#4 Other      2