使用 pivot_longer 从电子表格中重构具有多列的宽数据 数据

问题描述

我确定这个问题有答案,但我找不到。我尝试了使用多个 R 函数包括 reshape、gather 和 pivot_longer)的几种解决方案。我的问题是数据来自具有多列的电子表格。我将尝试表示电子表格的样本:

全名 SOCW725 SOCW748 SOCW799 平均 SOCW725 SOCW752 SOCW782 平均 SOCW725 SOCW748 SOCW752 平均
比维斯 B 3.5 3.22 2.56 3.07 2.33 3.33 4.2 3.5 3.33 3.23 无数据 3.00
El Guapo 3.25 3.02 2.75 3.18 3.33 4.33 4.15 2.25 2.67 3.42 4 2.44

实际的数据文件要宽得多。每组三门课程(例如 SOCW725、SOCW748、SOCW799)代表一种能力,共有九种能力。我把那些放在桌子上,因为我相信一旦我弄清楚了(我希望)我可以将它们插入到数据框中。因此,我试图将 pivot_longer 分成三列(添加 CompetencyID 时将为 4)。这些列是:名称、课程和评级。我不需要平均值,因为我可以重新计算。以下是我正在使用的代码示例:

d1 <- pivot_longer(my_data,cols = !1,names_to = "Course",values_to = "ratings",)

这有效,但重复的行名(即课程名称)有一个 .后跟一个数字(例如 SOCW725.1、SOCW725.2 等)。我明白为什么,但我不知道如何摆脱它。我大概可以弄清楚如何从结果中编辑 .#,但想找到一种更快的方法 dplyr::pivot_table。

提前致谢。

解决方法

如果我们有兴趣在单列中返回 'FullName' 和 'SOCW' 列(重复),select 感兴趣的列,然后使用 pivot_longernames_pattern 作为".value" 并从不带 . ([^.]+) 后跟数字的列名中捕获子字符串。

library(dplyr)
library(tidyr)
my_data %>% 
    select(FullName,starts_with("SOCW")) %>% 
    pivot_longer(cols = starts_with("SOCW"),names_to = ".value",names_pattern = '^(SOCW[^.]+)')
# A tibble: 6 x 6
  FullName SOCW725 SOCW748 SOCW799 SOCW752 SOCW782
  <chr>      <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
1 Beavis B    3.5     3.22    2.56    3.33    4.2 
2 Beavis B    2.33    3.23   NA      NA      NA   
3 Beavis B    3.33   NA      NA      NA      NA   
4 El Guapo    3.25    3.02    2.75    4.33    4.15
5 El Guapo    3.33    3.42   NA       4      NA   
6 El Guapo    2.67   NA      NA      NA      NA  

data.frame 默认不允许重复的列名。它使用 make.unique 通过为每个重复项附加 .1.2 等来修改列名称。


如果我们只需要三列

library(stringr)
my_data %>% 
   select(FullName,starts_with("SOCW")) %>% 
   pivot_longer(cols = starts_with("SOCW")) %>% 
   mutate(name = str_remove(name,"\\.\\d+$"))
# A tibble: 18 x 3
   FullName name    value
   <chr>    <chr>   <dbl>
 1 Beavis B SOCW725  3.5 
 2 Beavis B SOCW748  3.22
 3 Beavis B SOCW799  2.56
 4 Beavis B SOCW725  2.33
 5 Beavis B SOCW752  3.33
 6 Beavis B SOCW782  4.2 
 7 Beavis B SOCW725  3.33
 8 Beavis B SOCW748  3.23
 9 Beavis B SOCW752 NA   
10 El Guapo SOCW725  3.25
11 El Guapo SOCW748  3.02
12 El Guapo SOCW799  2.75
13 El Guapo SOCW725  3.33
14 El Guapo SOCW752  4.33
15 El Guapo SOCW782  4.15
16 El Guapo SOCW725  2.67
17 El Guapo SOCW748  3.42
18 El Guapo SOCW752  4   

数据

my_data <- structure(list(FullName = c("Beavis B","El Guapo"),SOCW725 = c(3.5,3.25),SOCW748 = c(3.22,3.02),SOCW799 = c(2.56,2.75),Average = c(3.07,3.18),SOCW725.1 = c(2.33,3.33),SOCW752 = c(3.33,4.33),SOCW782 = c(4.2,4.15),Average.1 = c(3.5,2.25),SOCW725.2 = c(3.33,2.67),SOCW748.1 = c(3.23,3.42),SOCW752.1 = c(NA,4L),Average.2 = c(3,2.44)),class = "data.frame",row.names = c(NA,-2L))
,

在您的帮助 akrun 下,我能够让它发挥作用:

d1 <- pivot_longer(my_data,cols = !1,names_to = "Course",values_to = "Ratings",names_pattern = '^(SOCW[^.]+)'
                    )

正则表达式在我要学习的清单上。