当需要来自 data.table 的 `measure = patterns("x", "y")` 时,使用 tidyverse (dplyr) 函数进行熔化

Melt using tidyverse (dplyr) functions, when needing `measure = patterns("x", "y")` from data.table

我有一个很好的很长的不同 tidyverse 命令管道,但在中途我需要使用 SetDT() %>% melt(...) %>% as_tibble()。我的代码工作正常,但我想知道使用 gather()pivot_longer() 的纯 tidyverse 解决方案是否可以为我做同样的事情。我试了很多,还是搞不明白。

这是示例数据框

library(tidyverse)
library(data.table)

df <- tibble(ID1 = c("A", "B", "C", "E", "F"),
             ID2 = 1:5,
             PR_1  = c(100, 150, 200, 250, 300),
             QL_1  = c(2.5, 4, 5, 2, 1),
             PR_2  = c(105, 150, 210, 275, 301),
             QL_2  = c(3, 4.5, 5.1, 2.5, 3))
df
# A tibble: 5 x 6
  ID1     ID2  PR_1  QL_1  PR_2  QL_2
  <chr> <int> <dbl> <dbl> <dbl> <dbl>
1 A         1   100   2.5   105   3  
2 B         2   150   4     150   4.5
3 C         3   200   5     210   5.1
4 E         4   250   2     275   2.5
5 F         5   300   1     301   3  

这是预期的结果

   ID1     ID2 variable    PR    QL
   <chr> <int> <chr>    <dbl> <dbl>
 1 A         1 1          100   2.5
 2 B         2 1          150   4  
 3 C         3 1          200   5  
 4 E         4 1          250   2  
 5 F         5 1          300   1  
 6 A         1 2          105   3  
 7 B         2 2          150   4.5
 8 C         3 2          210   5.1
 9 E         4 2          275   2.5
10 F         5 2          301   3  

我现在使用此代码(可以使用,但需要 data.table 包)

df %>%
  setDT() %>% 
  melt(id = c("ID1",  
              "ID2"),
       measure = patterns("^PR", "^QL"), 
       variable.factor = FALSE,
       value.name = c("PR", "QL")) %>%
  as_tibble()

我的问题是,tidyverse 的等价物是什么? 我真的很喜欢 data.table 包,但对于这个项目,我想坚持使用 tidyverse code

您可以使用 pivot_longer 如:

tidyr::pivot_longer(df, 
                    cols = -starts_with('ID'), 
                    names_to = c('.value', 'variable'), 
                    names_sep = "_")

# A tibble: 10 x 5
#   ID1     ID2 variable    PR    QL
#   <chr> <int> <chr>    <dbl> <dbl>
# 1 A         1 1          100   2.5
# 2 A         1 2          105   3  
# 3 B         2 1          150   4  
# 4 B         2 2          150   4.5
# 5 C         3 1          200   5  
# 6 C         3 2          210   5.1
# 7 E         4 1          250   2  
# 8 E         4 2          275   2.5
# 9 F         5 1          300   1  
#10 F         5 2          301   3  

你可以试试这个:

library(tidyverse)

df %>% pivot_longer(cols = names(df)[-c(1,2)]) %>%
  separate(name,into = c('char','var'),sep = '_') %>%
  pivot_wider(names_from = char,values_from = value)

# A tibble: 10 x 5
   ID1     ID2 var      PR    QL
   <chr> <int> <chr> <dbl> <dbl>
 1 A         1 1       100   2.5
 2 A         1 2       105   3  
 3 B         2 1       150   4  
 4 B         2 2       150   4.5
 5 C         3 1       200   5  
 6 C         3 2       210   5.1
 7 E         4 1       250   2  
 8 E         4 2       275   2.5
 9 F         5 1       300   1  
10 F         5 2       301   3