当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
您还可以使用 length
和 unique
到 filter
的组合:
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 个函数的变量(即 length
和 sum
),但我们想对每个组(ID
和Category
)。 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),]
我有一个 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
您还可以使用 length
和 unique
到 filter
的组合:
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 个函数的变量(即 length
和 sum
),但我们想对每个组(ID
和Category
)。 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),]