rdataframepivot

Pivot dataframe in R with multiple values


I'm attempting to pivot a dataframe with 8 columns of values which cover 4 variables over 2 years. I'm attempting to pivot it so that the year will be identified by a column and each variable will be it's own column.

It currently looks like this:

name <- c("James", "Ron", "Eli", "Emily")
A_2021 <- c(10, 15, 100, 20)
A_2022 <- c(30, 40, 8, 10)
B_2021 <- c(5, 5, 8, 7)
B_2022 <- c(17, 8, 9, 10)
C_2021 <- c(9, 9, 30, 18)
C_2022 <- c(100, 12, 4, 8)
D_2021 <- c(15, 18, 19, 20)
D_2022 <- c(20, 18, 19, 21)

df <- data.frame(name = name, A_2021 = A_2021, A_2022 = A_2022, B_2021 = B_2021, B_2022 = B_2022, C_2021 = C_2021, C_2022 = C_2022, D_2021 = D_2021, D_2022 = D_2022)

Output

1   James   10  30  5   17  9   100 15  20
2   Ron     15  40  5   8   9   12  18  18
3   Eli     100 8   8   9   30  4   19  19
4   Emily   20  10  7   10  18  8   20  21

And I want to make it look like this:

Name    A   B   C   D
James   10  5   9   15
James   30  17  100 20
Ron     15  5   9   18
Ron     40  8   12  18
Eli     100 8   30  19
Eli     8   9   4   19
Emily   20  7   18  20
Emily   10  10  8   21

I've been toying with pivot_longer but haven't been able to get it to work with multiple values.


Solution

  • They key is to use .value in the names_to value. That extracts the relevant part of the column names to be the new column name.

    library(tidyr)
    name <- c("James", "Ron", "Eli", "Emily")
    A_2021 <- c(10, 15, 100, 20)
    A_2022 <- c(30, 40, 8, 10)
    B_2021 <- c(5, 5, 8, 7)
    B_2022 <- c(17, 8, 9, 10)
    C_2021 <- c(9, 9, 30, 18)
    C_2022 <- c(100, 12, 4, 8)
    D_2021 <- c(15, 18, 19, 20)
    D_2022 <- c(20, 18, 19, 21)
    
    df <- data.frame(name = name, A_2021 = A_2021, A_2022 = A_2022, B_2021 = B_2021, B_2022 = B_2022, C_2021 = C_2021, C_2022 = C_2022, D_2021 = D_2021, D_2022 = D_2022)
    df |> pivot_longer(cols = -name, names_sep = "_", names_to = c(".value", "Year"))
    #> # A tibble: 8 × 6
    #>   name  Year      A     B     C     D
    #>   <chr> <chr> <dbl> <dbl> <dbl> <dbl>
    #> 1 James 2021     10     5     9    15
    #> 2 James 2022     30    17   100    20
    #> 3 Ron   2021     15     5     9    18
    #> 4 Ron   2022     40     8    12    18
    #> 5 Eli   2021    100     8    30    19
    #> 6 Eli   2022      8     9     4    19
    #> 7 Emily 2021     20     7    18    20
    #> 8 Emily 2022     10    10     8    21
    

    Created on 2025-01-01 with reprex v2.1.1