Растапливайте с помощью функций tidyverse (dplyr), когда требуется `measure = patterns (x, y)` из data.table

У меня есть хороший и довольно длинный канал различных команд tidyverse, но на полпути мне нужно использовать SetDT() %>% melt(...) %>% as_tibble(). Мой код работает нормально, но мне было интересно, может ли чистое решение tidyverse с использованием gather() или pivot_longer() сделать то же самое для меня. Я много пробовал, но не могу понять.

Это образец фрейма данных

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()

Мой вопрос в том, что было бы эквивалентом тидиверса? Мне очень нравится пакет data.table, но в этом проекте я хотел бы придерживаться только кода tidyverse.


person L Smeets    schedule 18.07.2020    source источник


Ответы (2)


Вы можете использовать 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  
person Ronak Shah    schedule 18.07.2020
comment
именно то, что я искал! - person L Smeets; 18.07.2020

Вы можете попробовать это:

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  
person Duck    schedule 18.07.2020
comment
Это тоже отлично работает, но немного менее элегантно, чем решение Ронака Шаха. - person L Smeets; 18.07.2020