用 dplyr 总结内部每个不同组的观察次数(n_distinct 等效?)
Count number of observations per distinct group inside summarise with dplyr (n_distinct equivalent?)
是否有一个函数可以像 n_distinct()
那样计算独特组内的观察次数,而不是不同组的数量?
我正在使用 dplyr
和 group_by()
汇总数据,并且我正在尝试计算每个不同分组变量的观察次数的均值。
df<-data.frame(id=c('A', 'A', 'A', 'B', 'B', 'C','C','C'),
id.2=c('1', '2', '2', '1','1','1','2','2'),
v=c(sample(1:10, 8)))
df%>%
group_by(id.2)%>%
summarise(n.mean=mean(n_distinct(id)),
v.mean=mean(v))
# A tibble: 2 × 3
id.2 n.mean v.mean
<chr> <dbl> <dbl>
1 1 3 5
2 2 2 4.5
我需要的是:
id.2 n.mean v.mean
1 1 5
2 2 4.5
因为
id.2==1 n.mean 是 A 的 1 个观察值,B 的 2 个观察值,C 的 1 个观察值的平均值,
> mean(1,2,1)
[1] 1
id.2==2 n.mean 是 A 的 2 个观察值的平均值,B 的 0 个,C 的 2 个,
mean(2,0,2)
[1] 2
我尝试先按 group_by(id, id.2)
分组以计算观察结果,然后在后续步骤中仅按 id.2 分组时传递这些计数,但这没有用(尽管我可能只是不我不知道如何用 dplyr 实现这个,因为我对 tidyverse 解决方案不是很有经验)
您没有正确使用 mean
。 mean(1, 2, 1)
忽略除第一个参数以外的所有参数,因此无论第二个和第三个位置的其他数字是什么,都会 return 1 。对于 id.2 == 1
,您需要 mean(c(1, 2, 1))
,即 returns 1.333。
我们可以使用table
快速计算id.2
的每个分组中id
的频率,然后取它们的平均值。我们可以在同一步骤中计算 v.mean
。
library(tidyverse)
df %>%
group_by(id.2) %>%
summarize(
n.mean = mean(table(id)),
v.mean = mean(v)
)
id.2 n.mean v.mean
<chr> <dbl> <dbl>
1 1 1.33 4.25
2 2 2 6
您的示例指出 id.2 == 2
没有 id == B
的任何值。不清楚您想要的解决方案是将其计为 zero-length 类别,还是干脆忽略它。上面的解决方案忽略了它。以下通过首先 complete
-ing 输入数据将其作为 zero-length 类别包括(注意新行 #7,其中包含 NA 数据):
df_complete <- complete(df, id.2, id)
id.2 id v
<chr> <chr> <int>
1 1 A 9
2 1 B 1
3 1 B 2
4 1 C 5
5 2 A 4
6 2 A 7
7 2 B NA
8 2 C 3
9 2 C 10
我们可以将 id
转换为因子数据,这将迫使 table
即使在零长度分组中也能保持其独特的水平:
df_complete %>%
group_by(id.2) %>%
mutate(id = factor(id)) %>%
filter(!is.na(v)) %>%
summarize(
n.mean = mean(table(id)),
v.mean = mean(v, na.rm = T)
)
id.2 n.mean v.mean
<chr> <dbl> <dbl>
1 1 1.33 4.25
2 2 1.33 6
或不依赖于table
的替代配方:
df_complete %>%
group_by(id.2, id) %>%
summarize(
n_rows = sum(!is.na(v)),
id_mean = mean(v)
) %>%
group_by(id.2) %>%
summarize(
n.mean = mean(n_rows),
v.mean = weighted.mean(id_mean, n_rows, na.rm = T)
)
id.2 n.mean v.mean
<chr> <dbl> <dbl>
1 1 1.33 4.25
2 2 1.33 6
请注意,在提供随机示例数据时,您应该使用set.seed
来控制随机化并确保可重复性。这是我使用的:
set.seed(0)
df<-data.frame(id=c('A', 'A', 'A', 'B', 'B', 'C','C','C'),
id.2=c('1', '2', '2', '1','1','1','2','2'),
v=c(sample(1:10, 8)))
是否有一个函数可以像 n_distinct()
那样计算独特组内的观察次数,而不是不同组的数量?
我正在使用 dplyr
和 group_by()
汇总数据,并且我正在尝试计算每个不同分组变量的观察次数的均值。
df<-data.frame(id=c('A', 'A', 'A', 'B', 'B', 'C','C','C'),
id.2=c('1', '2', '2', '1','1','1','2','2'),
v=c(sample(1:10, 8)))
df%>%
group_by(id.2)%>%
summarise(n.mean=mean(n_distinct(id)),
v.mean=mean(v))
# A tibble: 2 × 3
id.2 n.mean v.mean
<chr> <dbl> <dbl>
1 1 3 5
2 2 2 4.5
我需要的是:
id.2 n.mean v.mean
1 1 5
2 2 4.5
因为
id.2==1 n.mean 是 A 的 1 个观察值,B 的 2 个观察值,C 的 1 个观察值的平均值,
> mean(1,2,1)
[1] 1
id.2==2 n.mean 是 A 的 2 个观察值的平均值,B 的 0 个,C 的 2 个,
mean(2,0,2)
[1] 2
我尝试先按 group_by(id, id.2)
分组以计算观察结果,然后在后续步骤中仅按 id.2 分组时传递这些计数,但这没有用(尽管我可能只是不我不知道如何用 dplyr 实现这个,因为我对 tidyverse 解决方案不是很有经验)
您没有正确使用 mean
。 mean(1, 2, 1)
忽略除第一个参数以外的所有参数,因此无论第二个和第三个位置的其他数字是什么,都会 return 1 。对于 id.2 == 1
,您需要 mean(c(1, 2, 1))
,即 returns 1.333。
我们可以使用table
快速计算id.2
的每个分组中id
的频率,然后取它们的平均值。我们可以在同一步骤中计算 v.mean
。
library(tidyverse)
df %>%
group_by(id.2) %>%
summarize(
n.mean = mean(table(id)),
v.mean = mean(v)
)
id.2 n.mean v.mean
<chr> <dbl> <dbl>
1 1 1.33 4.25
2 2 2 6
您的示例指出 id.2 == 2
没有 id == B
的任何值。不清楚您想要的解决方案是将其计为 zero-length 类别,还是干脆忽略它。上面的解决方案忽略了它。以下通过首先 complete
-ing 输入数据将其作为 zero-length 类别包括(注意新行 #7,其中包含 NA 数据):
df_complete <- complete(df, id.2, id)
id.2 id v
<chr> <chr> <int>
1 1 A 9
2 1 B 1
3 1 B 2
4 1 C 5
5 2 A 4
6 2 A 7
7 2 B NA
8 2 C 3
9 2 C 10
我们可以将 id
转换为因子数据,这将迫使 table
即使在零长度分组中也能保持其独特的水平:
df_complete %>%
group_by(id.2) %>%
mutate(id = factor(id)) %>%
filter(!is.na(v)) %>%
summarize(
n.mean = mean(table(id)),
v.mean = mean(v, na.rm = T)
)
id.2 n.mean v.mean
<chr> <dbl> <dbl>
1 1 1.33 4.25
2 2 1.33 6
或不依赖于table
的替代配方:
df_complete %>%
group_by(id.2, id) %>%
summarize(
n_rows = sum(!is.na(v)),
id_mean = mean(v)
) %>%
group_by(id.2) %>%
summarize(
n.mean = mean(n_rows),
v.mean = weighted.mean(id_mean, n_rows, na.rm = T)
)
id.2 n.mean v.mean
<chr> <dbl> <dbl>
1 1 1.33 4.25
2 2 1.33 6
请注意,在提供随机示例数据时,您应该使用set.seed
来控制随机化并确保可重复性。这是我使用的:
set.seed(0)
df<-data.frame(id=c('A', 'A', 'A', 'B', 'B', 'C','C','C'),
id.2=c('1', '2', '2', '1','1','1','2','2'),
v=c(sample(1:10, 8)))