我想计算第1组、第2组和第3组的重量和高度汇总统计数据(平均,范围)。我特别想通过计算当第1组不为NA (对于calc组1)时计算汇总统计量来实现这一点,而对于第2组,当列不是NA时,我想要通过计算汇总统计量来实现这一点。
在下面的例子中,第1组的权重为3,2,第2组的权重为3,5。
dt <- tibble(
group1 = c(1, 1, NA, NA, NA, NA),
group2 = c(NA, NA, 2, 2, NA, NA),
group3 = c(NA, NA, NA, NA, 3, 3),
weight = c(3, 2, 3, 5, NA, 7),
height = c(10, NA, 14, 15, 11, 20)
)发布于 2021-08-28 13:23:13
你可以试试
library(dplyr)
library(tidyr)
dt %>%
group_by(group = coalesce(group1, group2, group3)) %>%
summarize(
mean_weight = mean(weight, na.rm = TRUE),
mean_height = mean(height, na.rm = TRUE)
)回传
# A tibble: 3 x 3
group mean_weight mean_height
<dbl> <dbl> <dbl>
1 1 2.5 10
2 2 4 14.5
3 3 7 15.5如果每一行有多个组,则可以使用
dt %>%
pivot_longer(
starts_with("group"),
values_drop_na = TRUE,
values_to = "group"
) %>%
group_by(group) %>%
summarize(
mean_weight = mean(weight, na.rm = TRUE),
mean_height = mean(height, na.rm = TRUE)
)它的返回基本相同。
# A tibble: 3 x 3
group mean_weight mean_height
<dbl> <dbl> <dbl>
1 1 2.5 10
2 2 4 14.5
3 3 7 15.5这是怎么回事?
pivot_longer将数据转换成“长”格式。我们以"group“(starts_with("group"))开头的每一列。这些列名进入新列name (默认名称,您可以用names_to = "YourNewColumnNameHere"更改它)。使用group将这些值放入新列values_to = "group"中。如果不使用此参数,则默认情况下值存储在列value中。values_drop_na = TRUE负责处理每个包含NA值的单元格。这些都被移除了。因此,在使用pivot_longer之后,转换后的数据看起来像# A tibble: 6 x 4
weight height name group
<dbl> <dbl> <chr> <dbl>
1 3 10 group1 1
2 2 NA group1 1
3 3 14 group2 2
4 5 15 group2 2
5 NA 11 group3 3
6 7 20 group3 3因此,下一个转换将应用于每个独立的组,不影响每个other.
summarize,接受分组并计算每个组的新列。所有其他列都会被删除。na.rm = TRUE参数mean()负责处理NA值:这些值被忽略。如果没有这个参数,组NA.
的mean_weight将是3
编辑
由于akrun注释,可以将其推广到多个列,而无需使用大爆炸运算符进行整形:
dt %>%
group_by(group = coalesce(!!! select(., starts_with('group')))) %>%
summarise(across(c(weight, height), mean, na.rm = TRUE))akrun使用了一种更高级的方法:
statement.
coalesce()的核心是NA-element的函数。例如:coalesce(NA_real_, 1, 2)返回1,因为这是第一个非NA-value。由于coalesce()是向量化的,所以coalesce(group1, group2, group3)和组列只包含一行中的一个值。
dt %>%
group_by(group = coalesce(group1, group2, group3))返回一个已经分组的tibble。
# A tibble: 6 x 6
# Groups: group [3]
group1 group2 group3 weight height group
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 NA NA 3 10 1
2 1 NA NA 2 NA 1
3 NA 2 NA 3 14 2
4 NA 2 NA 5 15 2
5 NA NA 3 NA 11 3
6 NA NA 3 7 20 3如果有许多/多个列名为
coalesce(group1, ... , group100)。所以我们使用一个函数,它选择所有的列。在这里,!!! select(., starts_with('group'))是最好的方法:将data.frame的每一列以"group“开头。不幸的是,select返回一个data.frame (这是向量列表的一个特殊版本)。我们需要为coalesce提供多个向量作为参数。向量列表无法完成任务:dt %>%
group_by(group = coalesce(select(., starts_with('group')))) 返回
# Groups: group [3]
group1 group2 group3 weight height group$group1 $group2 $group3
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 NA NA 3 10 1 NA NA
2 1 NA NA 2 NA 1 NA NA
3 NA 2 NA 3 14 NA 2 NA
4 NA 2 NA 5 15 NA 2 NA
5 NA NA 3 NA 11 NA NA 3
6 NA NA 3 7 20 NA NA 3这不是我们要找的。大爆炸算符!!!将这个向量列表分割成多个向量,这些向量作为参数提供给coalesce。所以
dt %>%
group_by(group = coalesce(!!! select(., starts_with('group')))) 返回
# A tibble: 6 x 6
# Groups: group [3]
group1 group2 group3 weight height group
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 NA NA 3 10 1
2 1 NA NA 2 NA 1
3 NA 2 NA 3 14 2
4 NA 2 NA 5 15 2
5 NA NA 3 NA 11 3
6 NA NA 3 7 20 3summarise函数:summarise(across(c(weight, height), mean, na.rm = TRUE))。across()告诉summarise将带参数na.rm = TRUE的函数mean应用于列weight和height。这是的一个更优雅的版本
summarize(
mean_weight = mean(weight, na.rm = TRUE),
mean_height = mean(height, na.rm = TRUE)
)如果没有重命名(这也可以用across完成)。
发布于 2021-08-28 19:08:08
带有data.table的选项
library(data.table)
setDT(dt)[, lapply(.SD, mean, na.rm = TRUE),
.(group = fcoalesce(group1, group2, group3)),
.SDcols = c('weight', 'height')]
group weight height
1: 1 2.5 10.0
2: 2 4.0 14.5
3: 3 7.0 15.5发布于 2021-08-28 12:46:16
您可以为每个组查找汇总统计信息,然后将NA过滤掉。以group1为例。
dt %>%
group_by(group1) %>%
summarise(mean_weight = mean(weight, na.rm=T),
mean_height = mean(height, na.rm=T),
.groups = 'drop') %>%
filter(!(is.na(group1)))https://stackoverflow.com/questions/68964417
复制相似问题