在条件来自另一列的数据框中求和

Summing across in a dataframe with condition coming from another column

这不是一个很好的问题标题。我想对每个组的数据框中的某些列求和,不包括我的每个组的一列。一个简单的例子如下:

df <- tibble(group_name = c("A", "B","C"), mean_A = c(1,2,3), mean_B = c(2,3,4), mean_C=c(3,4,5))
df %>% group_by(group_name) %>% mutate(m1 = sum(across(contains("mean"))))

这将创建列 m1,它是每个组的 mean_a、mean_b、mean_c 的总和。我想要做的是排除 a 组的 mean_a,b 组的 mean_b 和 c 组的 mean_c。但以下内容不起作用(不足为奇)。

df %>% group_by(group_name) %>% mutate(m1 = sum(across(c(contains("mean") & !contains(group_name)))))

你知道我该怎么做吗?我的原始数据包含更多组,因此很难手工完成。

编辑:我已经尝试了以下以基本方式解决它的方法,但是有些东西(可能是?grepl)在这里似乎效果不佳,我得到了错误的结果。

df %>% pivot_longer(!group_name) %>% mutate(value2 = case_when(grepl(group_name, name) ~ 0, TRUE ~ value)) %>% group_by(group_name) %>% summarise(m1 = sum(value2))

Edit2:发现上面有什么问题,下面是有效的,但仍然有很多警告,所以我建议人们遵循下面 TarJae 的回复

df %>% pivot_longer(!group_name) %>% group_by(group_name) %>% mutate(value2 = case_when(grepl(group_name, name) ~ 0, TRUE ~ value)) %>% group_by(group_name) %>% summarise(m1 = sum(value2))

这是我们可以做到的一种方法:

  1. 我们创建一个辅助列来匹配列名
  2. 如果列名称与助手名称匹配,我们将平均列的值设置为 zeor。
  3. 然后我们用transmuteselect计算rowSums
  4. 最后我们 cbindm1df:
library(dplyr)

df %>% 
  mutate(helper = paste0("mean_", group_name)) %>% 
  mutate(across(starts_with("mean"), ~ifelse(cur_column()==helper, 0, .))) %>%
  transmute(m1 = select(., contains("mean")) %>% 
           rowSums()) %>% 
  cbind(df)
  m1 group_name mean_a mean_b mean_c
1  5          a      1      2      3
2  6          b      2      3      4
3  7          c      3      4      5

这是另一个选项,您可以直接将 group_name 与 tidyselect 助手一起使用:

df %>% 
  rowwise() %>% 
  mutate(m1 = rowSums(select(across(starts_with("mean")), -ends_with(group_name)))) %>% 
  ungroup()

输出

  group_name mean_A mean_B mean_C    m1
  <chr>       <dbl>  <dbl>  <dbl> <dbl>
1 A               1      2      3     5
2 B               2      3      4     6
3 C               3      4      5     7

工作原理

  1. across 的 row-wise 输出是 1 行小标题,仅包含以 "mean".
  2. 开头的变量
  3. selectacross 的输出中取消选择以 group_name.
  4. 的值结尾的变量子集
  5. 此时您剩下一个 1 x 2 的小标题,然后使用 rowSums.
  6. 求和