两组列的平行枢纽_更长

des*_*hen 21 pivot r reshape tidyr

我有以下数据框:

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)
Run Code Online (Sandbox Code Playgroud)

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

dat_new <- dat %>%
  group_by(Scenario) %>%
  mutate_at(vars(-group_cols()), .funs = list(sum = sum))
Run Code Online (Sandbox Code Playgroud)

现在我想将这些数据转换为长格式,其中一组是我的 V1:V4 列,第二组是我的 V1_sum:V4_sum 列。正常的pivot_longer不起作用,因为它只接受一个值列,但是,我需要两个。

我在 tidyverse 参考中找到了一个潜在的解决方案(示例位于最底部),但我无法定义正确的names_pattern. https://tidyr.tidyverse.org/reference/pivot_longer.html

有没有一种简单直接的方法(最好是 tidyverse)可以让我做这两个 hub_longer 集?感觉这是重塑数据集时的基本任务之一,但我无法让它工作。

预期输出:

Scenario    set    V    sum
1           1      0.97 3.06
1           2      0.46 2.67
1           3      0.79 1.32
1           4      0.25 2.35
...
4           4      0.99 0.99
Run Code Online (Sandbox Code Playgroud)

注意:列名“set”、“V”和“sum”只是示例,如果其他列名更容易即时生成,我也可以接受。

emu*_*rak 26

vignette("pivot")在“每行多个观察”标题下找到了这个解决方案。

每组变量都需要一个并行的命名结构,并且需要一个分隔符。

对于寻找通用解决方案的用户,请跳至下面的“通用解决方案”部分。

准备询问者的示例数据

在你的情况下(这不是很普遍),从函数中出来mutate_at,你会_sum附加到每个变量。但是前四个变量的下划线后面需要一些东西。我用标签重命名了原来的四个变量,_orig并将总和变量的名称从V1_orig_sum到简化了V1_sum,以避免使用双下划线。

dat <- tribble(
  ~Scenario,     ~V1_orig,    ~V2_orig,    ~V3_orig,    ~V4_orig,
  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)

dat_new <- dat %>%
  group_by(Scenario) %>%
  mutate_at(vars(-group_cols()), .funs = list(sum = sum)) %>%
  rename_with(.cols=ends_with('_sum'), .fn=str_remove, pattern='_orig')
Run Code Online (Sandbox Code Playgroud)

经过这些操作后,您的数据将采用适合回答pivot_longer()两组列的格式(如下一节所示)。

通用解决方案

我们从一个数据框开始,dat_new该数据框具有一个 ID 变量 ( Scenario) 和两组,每组四列:

> head(dat_new)
# A tibble: 6 x 9
# Groups:   Scenario [2]
  Scenario V1_orig V2_orig V3_orig V4_orig V1_sum V2_sum V3_sum V4_sum
     <dbl>   <dbl>   <dbl>   <dbl>   <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
1        1    0.97    0.46    0.79    0.25   3.06   2.67   1.32   2.35
2        1    0.21    0.45    0.23    0.63   3.06   2.67   1.32   2.35
3        1    0.95    0.97    0.07    0.61   3.06   2.67   1.32   2.35
4        1    0.93    0.79    0.23    0.86   3.06   2.67   1.32   2.35
5        2    0.22    0.01    0.42    0.47   0.93   0.18   0.58   1.35
6        2    0.71    0.17    0.16    0.88   0.93   0.18   0.58   1.35
Run Code Online (Sandbox Code Playgroud)

列名称的形式为[row]_[column], where[row][column]描述我们希望组件在最终数据框中显示的位置。

调用pivot_longer但在参数中给它两个列名称names_to:一个用于您调用这些对象的名称(Var在本例中),并".value"指示分隔符后面有唯一标记时应该有尽可能多的新列_

dat_new %>% 
  pivot_longer(-Scenario, 
               names_to = c("Var", ".value"), 
               names_sep="_" )
# A tibble: 48 x 4
# Groups:   Scenario [4]
   Scenario Var    orig   sum
      <dbl> <chr> <dbl> <dbl>
 1        1 V1     0.97  3.06
 2        1 V2     0.46  2.67
 3        1 V3     0.79  1.32
 4        1 V4     0.25  2.35
 5        1 V1     0.21  3.06
 6        1 V2     0.45  2.67
 7        1 V3     0.23  1.32
 8        1 V4     0.63  2.35
 9        1 V1     0.95  3.06
10        1 V2     0.97  2.67
# ... with 38 more rows
Run Code Online (Sandbox Code Playgroud)

请注意,如果您的变量具有相反的命名系统(即orig_V1sum_V1等),您可以反转命名参数中的顺序:names_to=c(".value", "Var)。该解决方案不要求值是相同类型(即,orig 和 sum 在这里都是数字,但一个可以是数字,一个可以是字符)。