【问题标题】:R pivot multiple columns into long formatR将多列转换为长格式
【发布时间】:2020-04-16 16:39:36
【问题描述】:

我有一个宽格式的人员级别数据框,我正试图将它融合到一个长格式的汇总表中。示例代码和示例如下:

set.seed(100)

#Original wide format person level data
dat_wide <- tibble(group = rep(x = c('a','b','c'), each = 5),
                   d1 = sample(x = c(1, 0, NA_integer_), size = 15, replace = TRUE),
                   d2 = sample(x = c(1, 0, NA_integer_), size = 15, replace = TRUE),
                   d3 = sample(x = c(1, 0, NA_integer_), size = 15, replace = TRUE)) %>% 
  mutate(d1_br = case_when(
    d1 == 1 ~ .8,
    d1 == 0 ~ .2,
    TRUE ~ NA_real_
  ),
  d2_br = case_when(
    d2 == 1 ~ .6,
    d2 == 0 ~ .4,
    TRUE ~ NA_real_
  ),
  d3_br = case_when(
    d3 == 1 ~ .95,
    d3 == 0 ~ .05,
    TRUE ~ NA_real_
  ))
dat_wide

# A tibble: 15 x 7
   group    d1    d2    d3 d1_br d2_br d3_br
   <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
 1 a         0    NA     0   0.2  NA    0.05
 2 a         1     0     0   0.8   0.4  0.05
 3 a         1    NA     1   0.8  NA    0.95
 4 a         1    NA    NA   0.8  NA   NA   
 5 a         0    NA     1   0.2  NA    0.95
 6 b        NA     0     1  NA     0.4  0.95
 7 b        NA    NA     1  NA    NA    0.95
 8 b        NA     0     1  NA     0.4  0.95
 9 b         1     0     0   0.8   0.4  0.05
10 b         1     1    NA   0.8   0.6 NA   
11 c         0    NA     1   0.2  NA    0.95
12 c         0    NA     0   0.2  NA    0.05
13 c        NA    NA     1  NA    NA    0.95
14 c         1    NA     0   0.8  NA    0.05
15 c         0     1     0   0.2   0.6  0.05

#Long format summary table
dat_long <- tibble(group = rep(c('a','b','b'), each = 9),
                   dv = rep(c('d1','d2','d3'), each = 3, times = 3),
                   response = rep(c(1, 0, NA_integer_), times = 9)) %>% 
  mutate(br = case_when(
    dv == 'd1' & response == 1 ~ .8,
    dv == 'd1' & response == 0 ~ .2,
    dv == 'd2' & response == 1 ~ .6,
    dv == 'd2' & response == 0 ~ .4,
    dv == 'd3' & response == 1 ~ .95,
    dv == 'd3' & response == 0 ~ .05,
    TRUE ~ NA_real_
  ))

# A tibble: 27 x 4
   group dv    response    br
   <chr> <chr>    <dbl> <dbl>
 1 a     d1           1  0.8 
 2 a     d1           0  0.2 
 3 a     d1          NA NA   
 4 a     d2           1  0.6 
 5 a     d2           0  0.4 
 6 a     d2          NA NA   
 7 a     d3           1  0.95
 8 a     d3           0  0.05
 9 a     d3          NA NA   
10 b     d1           1  0.8 
# ... with 17 more rows

我相当肯定这可以通过tidyr::pivot_longer 完成,尽管我是新手,还没有弄清楚它的所有功能。类似于以下内容的东西应该可以工作,但是有人可以帮助填写 pivot_longer 语法吗?我需要names_sepnames_prefix 参数吗?我还没有完全理解这些。

#Possible solution
dat_long <- dat_wide %>% 
  # pivot_longer(...) %>% 
  distinct(group, dv, response, .keep_all = TRUE)

【问题讨论】:

    标签: r dplyr tidyverse reshape tidyr


    【解决方案1】:

    如果列名中的数值始终保持在末尾,这可能会更容易。如果你重命名dat_wide:

    names(dat_wide) <- sub("(\\w+)(\\d+)(\\w*)", "\\1\\3\\2", names(dat_wide))
    

    d1_br 将变为 d_br1 等等。

    那么您可以使用pivot_longer 与两组列:

    library(tidyverse)
    
    dat_wide %>%
      pivot_longer(cols = -group, 
                   names_to = c(".value", "dv"),
                   names_pattern = "(\\w+)(\\d+)") %>%
      distinct(group, dv, d, .keep_all = TRUE) %>%
      arrange(group, dv)
    

    输出

    # A tibble: 24 x 4
       group dv        d  d_br
       <chr> <chr> <dbl> <dbl>
     1 a     1         0  0.2 
     2 a     1        NA NA   
     3 a     1         1  0.8 
     4 a     2        NA NA   
     5 a     2         0  0.4 
     6 a     2         1  0.6 
     7 a     3        NA NA   
     8 a     3         0  0.05
     9 a     3         1  0.95
    10 b     1         0  0.2 
    

    【讨论】:

    • 我目前正在努力实现这一点。你能解释一下 .value 哨兵实际上做了什么吗?
    • 特殊的.value sentinel 表示您的value 列的名称(在本例中为dd_br)。我们不需要使用values_to 来指示值在pivot_longer 中的位置。基于 names_pattern 正则表达式,您将获得 2 个不同的组件。第一个是数字前的字符串/单词,即dd_br。当您在 names_to 中使用 .value 时,这些将成为存储您的值的列名。第二个组成部分是数字 1、2 或 3,从原始列名中提取,然后包含在新的 dv 列下。
    • 这确实有效,尽管它调整了值,我不得不将它们修复回原来的值。我仍然不太明白我做了什么,但感谢您的帮助。
    猜你喜欢
    • 2020-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-25
    • 1970-01-01
    • 1970-01-01
    • 2021-09-28
    相关资源
    最近更新 更多