分组后使用 dplyr 按列划分的多个比率
Multiple ratios by column-wise division with dplyr following grouping
我有一个 df
需要按多列分组,以便随后计算不同列的子集的比率以及逐行均值和标准差。
grouper1 grouper2 condition value
foo baz A 1
foo baz B 2
foo oof A 1
foo oof C 3
bar zab B 2
bar zab C 4
基于这个优雅的 我已经成功构建了一个通用的解决方案:
library(dplyr)
library(tidyr)
library(purrr)
library(stringr)
crossing(c("A"), c("B","C")) %>%
pmap(~ query %>%
group_by(grouper1, grouper2) %>%
summarise(!! str_c('ratio_', ..1, ..2) :=
value[condition == ..1]/value[condition == ..2])) %>%
reduce(full_join, by = c('grouper1', 'grouper2')) %>%
ungroup() %>% mutate(mean=rowMeans(select(.,-(grouper1, grouper2)), SD=unlist(pmap(select(.,-(grouper1, grouper2)), ~sd(c(...)))))
如果在所有组中都找到 condition
列中的所有值,则此方法效果很好。如果不是这种情况,例如A
在上例中使用 grouper1
的第二个分组中不存在,我将收到以下错误:
Error: Column ratio_AC must be length 1 (a summary value), not 0
我显然可以预先选择 crossing
的值,但这需要对 df
进行筛选,这样我就失去了通用性。因此,我想要一个简单地忽略缺失组合并仍然计算指标的解决方案。
一个可能的解决方案是 pivot_wider
,但在这里我无法实施计算比率的有效解决方案。
我们可以使用 pivot_wider
重塑为宽格式,然后使用该数据集
library(dplyr)
library(tidyr)
library(purrr)
library(stringr)
df1 <- df %>%
pivot_wider(names_from = condition, values_from = value)
crossing(v1 = c("A"), v2 = c("B","C")) %>%
pmap(~ df1 %>%
transmute(grouper1, grouper2,
!! str_c('ratio_', ..1, ..2) :=
.[[..1]]/.[[..2]]))%>%
reduce(full_join, by = c('grouper1', 'grouper2')) %>%
mutate(mean = rowMeans(select(., -grouper1, -grouper2), na.rm = TRUE),
SD= pmap_dbl(select(., -grouper1, -grouper2),
~sd(c(...), na.rm = TRUE)))
数据
df <- structure(list(grouper1 = c("foo", "foo", "foo", "foo", "bar",
"bar"), grouper2 = c("baz", "baz", "oof", "oof", "zab", "zab"
), condition = c("A", "B", "A", "C", "B", "C"), value = c(1L,
2L, 1L, 3L, 2L, 4L)), class = "data.frame", row.names = c(NA,
-6L))
我有一个 df
需要按多列分组,以便随后计算不同列的子集的比率以及逐行均值和标准差。
grouper1 grouper2 condition value
foo baz A 1
foo baz B 2
foo oof A 1
foo oof C 3
bar zab B 2
bar zab C 4
基于这个优雅的
library(dplyr)
library(tidyr)
library(purrr)
library(stringr)
crossing(c("A"), c("B","C")) %>%
pmap(~ query %>%
group_by(grouper1, grouper2) %>%
summarise(!! str_c('ratio_', ..1, ..2) :=
value[condition == ..1]/value[condition == ..2])) %>%
reduce(full_join, by = c('grouper1', 'grouper2')) %>%
ungroup() %>% mutate(mean=rowMeans(select(.,-(grouper1, grouper2)), SD=unlist(pmap(select(.,-(grouper1, grouper2)), ~sd(c(...)))))
如果在所有组中都找到 condition
列中的所有值,则此方法效果很好。如果不是这种情况,例如A
在上例中使用 grouper1
的第二个分组中不存在,我将收到以下错误:
Error: Column ratio_AC must be length 1 (a summary value), not 0
我显然可以预先选择 crossing
的值,但这需要对 df
进行筛选,这样我就失去了通用性。因此,我想要一个简单地忽略缺失组合并仍然计算指标的解决方案。
一个可能的解决方案是 pivot_wider
,但在这里我无法实施计算比率的有效解决方案。
我们可以使用 pivot_wider
重塑为宽格式,然后使用该数据集
library(dplyr)
library(tidyr)
library(purrr)
library(stringr)
df1 <- df %>%
pivot_wider(names_from = condition, values_from = value)
crossing(v1 = c("A"), v2 = c("B","C")) %>%
pmap(~ df1 %>%
transmute(grouper1, grouper2,
!! str_c('ratio_', ..1, ..2) :=
.[[..1]]/.[[..2]]))%>%
reduce(full_join, by = c('grouper1', 'grouper2')) %>%
mutate(mean = rowMeans(select(., -grouper1, -grouper2), na.rm = TRUE),
SD= pmap_dbl(select(., -grouper1, -grouper2),
~sd(c(...), na.rm = TRUE)))
数据
df <- structure(list(grouper1 = c("foo", "foo", "foo", "foo", "bar",
"bar"), grouper2 = c("baz", "baz", "oof", "oof", "zab", "zab"
), condition = c("A", "B", "A", "C", "B", "C"), value = c(1L,
2L, 1L, 3L, 2L, 4L)), class = "data.frame", row.names = c(NA,
-6L))