tidyverse在以后的n个位置将几列除以其他列(避免循环)

时间:2019-12-09 18:00:49

标签: r tidyverse

library(tidyverse)
dat <- tribble(
  ~Scenario,     ~V1,    ~V2,    ~V3,    ~V4,
  1,    0.97,   0.46,   0.79,   0.25,
  1,    0.21,   0.45,   0.23,   0.63,
  1,    0.95,   0.97,   0.07,   0.61,
  1,    0.93,   0.79,   0.23,   0.86,
  2,    0.22,   0.01,   0.42,   0.47,
  2,    0.71,   0.17,   0.16,   0.88,
  3,    0.73,   0.38,   0.10,   0.77,
  3,    0.49,   0.37,   0.90,   0.52,
  3,    0.99,   0.71,   0.66,   0.05,
  3,    0.72,   0.75,   0.69,   0.01,
  3,    0.15,   0.87,   0.12,   0.02,
  4,    0.94,   0.30,   0.91,   0.99)

我要向该数据添加四个新列,其中每个新列代表按方案分组的每个V1:V4列的总和:

dat_new <- dat %>%
  group_by(Scenario) %>%
  mutate_at(vars(-group_cols()), .funs = list(sum = sum))

我正在寻找一种简单的方法将V1除以V1_sum,将V2除以V2_sum,以此类推,假设a)我的原始v列与sum列一样多,b)数据正确排序并遵循我的模式是我首先拥有所有v列,然后是sum列。

我只是在这里问了另一个问题,重点是将数据转换为长格式,然后再将其转换回宽格式,但是我想知道tidyverse中是否有更简单的解决方案。

注意:我大概可以遍历每列,然后再将其除以列4的位置,但是我正在寻找一种更优雅的解决方案。

1 个答案:

答案 0 :(得分:2)

我们可以在list内扩展功能,而不是创建临时的sum列然后进行划分

library(dplyr)
dat %>% 
   group_by(Scenario) %>% 
   mutate_at(vars(-group_cols()), .funs = list(percentage =  ~ ./sum(.)))

如果来自dat_new,则一个选项为map

library(purrr)
map2_dfc(dat %>% 
             select(V1:V4), 
        dat_new %>% 
             ungroup %>%
             select(ends_with('sum')), `/`)

或使用base R

dat[2:5]/dat_new[6:9]