Search code examples
rdataframetidyversedata-conversion

R Converting Wide Data to Long


How can I convert my data from this:

example <- data.frame(RTD_1_LOC = c('A', 'B'), RTD_2_LOC = c('C', 'D'),
                      RTD_3_LOC = c('E', 'F'), RTD_4_LOC = c('G', 'H'),
                      RTD_5_LOC = c('I', 'J'),RTD_1_OFF = c('1', '2'), RTD_2_OFF = c('3', '4'),
                      RTD_3_OFF = c('5', '6'), RTD_4_OFF = c('7', '8'),
                      RTD_5_OFF = c('9', '10'))

to this:

example2 <- data.frame(RTD = c(1,1,2,2,3,3,4,4,5,5),LOC = c('A', 'B','C','D','E','F','G','H','I','J'),
                       OFF = c(1,2,3,4,5,6,7,8,9,10))

I have been using tidyverse gather, but I end up with about 50 columns

ex <- gather(example,RTD, Location, RTD_1_LOC:RTD_5_LOC) 
ex$RTD <- sub('_LOC',"",ex$RTD)


ex3 <- gather(ex,RTD, Offset, RTD_1_OFF:RTD_5_OFF)
ex2$RTD <- sub('_OFF',"",ex2$RTD)

Solution

  • We can use pivot_longer from tidyr and specify the names_pattern to capture the groups from the column names. As the 'RTD' column should be left as such, specify in the names_to, a vector of 'RTD' and the column values (.value) so that the 'RTD' will get the digits capture ((\\d+) and the word ((\\w+)) 'LOC', 'OFF' will be created as new columns with the column values

    library(dplyr)
    library(tidyr)
     example %>% 
         pivot_longer(cols = everything(), 
          names_to = c("RTD", ".value"), names_pattern = "\\w+_(\\d+)_(\\w+)")
    

    -output

    # A tibble: 10 x 3
       RTD   LOC   OFF  
       <chr> <chr> <chr>
     1 1     A     1    
     2 2     C     3    
     3 3     E     5    
     4 4     G     7    
     5 5     I     9    
     6 1     B     2    
     7 2     D     4    
     8 3     F     6    
     9 4     H     8    
    10 5     J     10