将宽数据转换为具有多个变量的长格式

这可能有一个简单的答案,但经过几个小时的搜索后,我仍然找不到它。基本上我需要将宽数据集转换为长格式数据集,但具有多个变量。我的数据集结构如下所示:

df1 <- data.frame(id = c(1,2,3),
                  sex = c("M","F","M"),
                  day0s = c(21,25,15),
                  day1s = c(20,30,18),
                  day2s = c(18,18,17),
                  day0t = c(2,5,7),
                  day1t = c(3,6,5),
                  day2t = c(3,8,7))
df1
 id sex day0s  day1s  day2s day0t  day1t  day2t
 1   M    21     20     18     2      3      3
 2   F    25     30     18     5      6      8
 3   M    15     18     17     7      5      7

基本上 3 个科目每天都做数学测试 (s) 和历史测试 (t),持续 3 天。我尝试使用 tidyr 中的 collect 将其转换为长格式,但我不知道如何将 mt 和 ht 变量分配给同一天。我还编写了一个新的变量 day,只有 day0 = 0、day1 = 1 和 day2 = 2。

dfl ?- df1 %?%
  gather(day, value, - c(id,sex))
dfl
id sex  variable value  day
1   M   day0s     21    0
1   M   day1s     20    1
1   M   day2s     18    2
1   M   day0t      2    0
1   M   day1t      3    1
1   M   day2t      3    2
2   F   day0s     25    0
2   F   day1s     30    1
2   F   day2s     18    2
2   F   day0t      5    0
2   F   day1t      6    1
2   F   day2t      8    2
3   M   day0s     15    0
3   M   day1s     18    1
3   M   day2s     17    2
3   M   day0t      7    0
3   M   day1t      5    1
3   M   day2t      7    1

理想情况下,它最终应该是这样的。

id sex   day   s     t
1   M     0    21    2
1   M     1    20    3
1   M     2    18    3
2   F     0    25    5
2   F     1    30    6
2   F     2    18    8
3   M     0    15    7
3   M     1    18    5
3   M     2    17    7

您对如何实现这一目标有什么建议吗?

回答

您可以pivot_longer在此处使用 {tidyr} 。

如果您的实际变量命名有点不同,您可以根据您的情况调整正则表达式。在这里,您可以尝试并相应地进行调整。(请注意,在 R 中必须转义反斜杠,因此在d+and 中使用双反斜杠w+

一般来说,names_pattern参数的工作原理是将括号内的正则表达式与names_to参数匹配,因此这里:

  • (d+)-> 成为可变日。正则表达式d+匹配 1 个或多个数字。
  • (w+)-> 变成“.value”。正则表达式w+匹配 1 个或多个单词字符。感谢r2evans指出了“.value”参数,从而避免了进一步的重塑。该文档指出.value“讲述pivot_longer(),该列名的一部分指定‘值’被测量(其将成为输出一个变量)”。虽然我没有完全理解文档解释,但结果是匹配的正则表达式被映射到输出数据中的变量名称。
library(dplyr)
library(tidyr)

df1 <- data.frame(id = c(1,2,3),
                  sex = c("M","F","M"),
                  day0mt = c(21,25,15),
                  day1mt = c(20,30,18),
                  day2mt = c(18,18,17),
                  day0ht = c(2,5,7),
                  day1ht = c(3,6,5),
                  day2ht = c(3,8,7))

df1
#>   id sex day0mt day1mt day2mt day0ht day1ht day2ht
#> 1  1   M     21     20     18      2      3      3
#> 2  2   F     25     30     18      5      6      8
#> 3  3   M     15     18     17      7      5      7

df1 %>%
  pivot_longer(cols = starts_with("day"),
               names_pattern = "day(d+)(w+)",
               names_to = c("day", ".value"))
#> # A tibble: 9 x 5
#>      id sex   day      mt    ht
#>   <dbl> <chr> <chr> <dbl> <dbl>
#> 1     1 M     0        21     2
#> 2     1 M     1        20     3
#> 3     1 M     2        18     3
#> 4     2 F     0        25     5
#> 5     2 F     1        30     6
#> 6     2 F     2        18     8
#> 7     3 M     0        15     7
#> 8     3 M     1        18     5
#> 9     3 M     2        17     7

由reprex 包( v2.0.0 )于 2021 年 6 月 20 日创建

请注意,在较新版本的 tidyr 中,gatherspread被弃用并由pivot_longer和取代pivot_wider.

  • Use `names_to = c("day", ".value")` and remove the `pivot_wider` 🙂

以上是将宽数据转换为具有多个变量的长格式的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>