当ID存在于多个组中时,R dplyr组汇总和过滤

R dplyr group summarize and filter when ID exists in multiple groups

我有一个 table,带有 ID、类别和金额,有几千条记录。

数据:

df1 <- data.frame(
  ID = c('V1', 'V1', 'V1', 'V3', 'V3', 'V3', 'V4', 'V5','V5','V5'),
  Category = c('a', 'a', 'a', 'a', 'b', 'b', 'a', 'b', 'c', 'c'),
  Amount   = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1))

我想使用 dplyr 按 ID 和类别分组,对每组的总金额求和,然后过滤结果以仅包含存在于多个类别中的 ID。

结果:

ID  Category Amount_Sum
V3  a        1
V3  b        2
V5  b        1
V5  c        2

我有以下分组和求和的代码,但缺少当 ID 在多个组中时如何过滤

代码:

x <- df1 %>% 
       group_by(ID, Category) %>% 
       summarize(CNT = n(), amount = sum(Amount)) %>% 
       filter(????????)

Category 上使用 n_distinct 应该会给你想要的结果:

library(dplyr)

df1 %>% 
  group_by(ID, Category) %>% 
  summarize(CNT = n(), amount = sum(Amount)) %>% 
  filter(n_distinct(Category) > 1) %>%
  ungroup()

returns

# A tibble: 4 x 4
  ID    Category   CNT amount
  <chr> <chr>    <int>  <dbl>
1 V3    a            1      1
2 V3    b            2      2
3 V5    b            1      1
4 V5    c            2      2

您还可以使用 lengthuniquefilter 的组合:

library(dplyr)

df1 %>% 
  group_by(ID, Category) %>% 
  summarize(CNT = n(), amount = sum(Amount)) %>% 
  filter(length(unique(Category)) > 1)

输出

  ID    Category   CNT amount
  <chr> <chr>    <int>  <dbl>
1 V3    a            1      1
2 V3    b            2      2
3 V5    b            1      1
4 V5    c            2      2

或者这是一个基本的 R 选项,使用 aggregate 进行汇总,然后使用 ave 进行过滤。在这里,Amount 是我们要应用 2 个函数的变量(即 lengthsum),但我们想对每个组(IDCategory)。 aggregate 将 return 一个矩阵,结果在 2 列中。因此,为了将它们与数据框的其余部分集成,我们可以使用 do.call 将这些列中的每一列绑定到数据框。然后,我们可以使用 setNames.

重命名具有所需列名的列
df1_output <-
  setNames(do.call(
    data.frame,
    aggregate(
      Amount ~ ID + Category,
      data = df1,
      FUN = function(x)
        c(CNT = length(x), amount = sum(x))
    )
  ), c(names(df1[1:2]), "CNT", "amount"))


df1_output[with(df1_output, ave(Category, ID, FUN = function(x) length(unique(x))) > 1),]