Search code examples
rdplyrpivot

Pivot longer for multiple group of columns


For multiple individuals (ident column), i have multiple instances that are calculated at different time points. In my real database i have like more than 10 time points and more than 10 instances. Here as the example i only use 2 time points (M0 & M3) and 2 instances (abc & def):

I would like to keep the ident column and pivot_longer to have 2 columns after : abc and def . I succeed to do it if it's only for one instance, with the names_pattern options, but i struggle to apply that to more than one instance. I tried by having values_to=c("abc",def") but then i don't know what to put in the regex pattern.

data = data.frame(ident=c("A","B","C","D","E"),
                  M0_abc=c(1,0,1,0,1),
                  M0_def=c(1,1,1,1,0),
                  M3_abc=c(1,1,0,0,0),
                  M3_def=c(0,1,0,1,0))
> data
  ident M0_abc M0_def M3_abc M3_def
1     A      1      1      1      0
2     B      0      1      1      1
3     C      1      1      0      0
4     D      0      1      0      1
5     E      1      0      0      0

data_long <- data %>% select(ident, contains("abc")) %>%
  pivot_longer(cols=contains("abc"),
               names_to="time",
               values_to="abc",
               names_pattern = "(.*)_abc")

> data_long
# A tibble: 10 × 3
   ident time    abc
   <chr> <chr> <dbl>
 1 A     M0        1
 2 A     M3        1
 3 B     M0        0
 4 B     M3        1
 5 C     M0        1
 6 C     M3        0
 7 D     M0        0
 8 D     M3        0
 9 E     M0        1
10 E     M3        0


Solution

  • In case of multiple value columns you could use the special ".value" like so:

    library(tidyr)
    library(dplyr, warn = FALSE)
    
    data %>%
      pivot_longer(
        -ident,
        names_to = c("time", ".value"),
        names_pattern = "(.*)_(.*)"
      )
    #> # A tibble: 10 × 4
    #>    ident time    abc   def
    #>    <chr> <chr> <dbl> <dbl>
    #>  1 A     M0        1     1
    #>  2 A     M3        1     0
    #>  3 B     M0        0     1
    #>  4 B     M3        1     1
    #>  5 C     M0        1     1
    #>  6 C     M3        0     0
    #>  7 D     M0        0     1
    #>  8 D     M3        0     1
    #>  9 E     M0        1     0
    #> 10 E     M3        0     0