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_V1、sum_V1等),您可以反转命名参数中的顺序:names_to=c(".value", "Var)。该解决方案不要求值是相同类型(即,orig 和 sum 在这里都是数字,但一个可以是数字,一个可以是字符)。