Pivot_Longer创建多个组合列

时间:2019-10-03 03:15:38

标签: r tidyr

我已经在其他地方看到了关于我的问题的一些可能的讨论,但是它要么没有解决,要么我无法完全理解答案是否适用,所以我创建了一个新问题。

以下问题特别涉及此主题,但尚未解决。 Gathering wide columns into multiple long columns using pivot_longer

获取以下示例数据。如您所见,有一个唯一的标识符变量,然后是其他8个变量。在其他8个中,您可以将它们分为两组,gpa和percent_a。对于每个集合,都有一个类,组,课程和部门值。

在我的实际数据中,我有大约20个不同的集合,每个集合都具有相同的结构,每个集合中都有相同的四个描述符。

我想做的是执行类似于pivot_longer的功能。除了将多个列组合为一组键和值列之外,我数据中的每个唯一集(类,组,课程,部门)都将被分组到自己的键/值列中。

set.seed(101)
df <- data.frame(
  id = 1:10,
  class_gpa = rnorm(10, 0, 1),
  course_gpa = rnorm(10, 0, 1),
  group_gpa = rnorm(10, 0, 1),
  dept_gpa = rnorm(10, 0, 1),
  class_percent_a = rnorm(10, 0, 1),
  course_percent_a = rnorm(10, 0, 1),
  group_percent_a = rnorm(10, 0, 1),
  dept_percent_a = rnorm(10, 0, 1)
)

因此,在此示例中,假设我将所有gpa值分为两列(gpa_type和gpa_value),并将percent_a值分为两列(percent_a_type,percent_a_value),那么最后我只能得到5列:

id,gpa_type,gpa_value,percent_a_type,percent_a_value

有没有办法做到这一点?使用pivot_longer或其他方法。谢谢。

1 个答案:

答案 0 :(得分:0)

老实说,我宁愿做:

df %>% pivot_longer(-id, names_to = c("type", ".value"), names_pattern = "([^_]+)_(.*)")

并将数据保留为更实用的格式:

# A tibble: 40 x 4
      id type      gpa percent_a
   <int> <chr>   <dbl>     <dbl>
 1     1 class  -0.326     0.482
 2     1 course  0.526    -1.15 
 3     1 group  -0.164    -0.260
 4     1 dept    0.895     1.51 
 5     2 class   0.552     0.758
 6     2 course -0.795    -0.274
 7     2 group   0.709    -1.41 
 8     2 dept    0.279     1.62 
 9     3 class  -0.675    -2.32 
10     3 course  1.43      0.578
# … with 30 more rows

为什么要为每个“集合”重复“类型”属性?

为您所需的输出:

# A tibble: 40 x 5
      id gpa_type gpa_value percent_a_type percent_a_value
   <int> <chr>        <dbl> <chr>                    <dbl>
 1     1 class       -0.326 class                    0.482
 2     1 course       0.526 course                  -1.15 
 3     1 group       -0.164 group                   -0.260
 4     1 dept         0.895 dept                     1.51 
 5     2 class        0.552 class                    0.758
 6     2 course      -0.795 course                  -0.274
 7     2 group        0.709 group                   -1.41 
 8     2 dept         0.279 dept                     1.62 
 9     3 class       -0.675 class                   -2.32 
10     3 course       1.43  course                   0.578
# … with 30 more rows

您可以尝试:

lst_df <- df %>%
  gather(key, value, -id) %>%
  extract(key, into = c("var", "type"), "([^_]+)_(.*)") %>%
  split(.$type) 

names(lst_df) %>% 
  map_dfc(~ setNames( 
    lst_df[[.x]] %>% 
      select(-type), 
    c("id", paste0(.x, c("_type", "_value"))))) %>%
  select(-matches("id\\d+"))