rliststackreshapemeld

Turn rows to columns, then stack into single column using R


I have a dataframe of data which I need to convert to use for a panel study. I want to convert my rows into columns, then stack the columns into a single column. My current data:

STATE    1970   1971   1972   1973...2018
State-A  X      X      X      X       X
State-B  X      X      X      X       X
State-C  X      X      X      X       X

What I need:

Year   State  Data
1970    A      X
1971    A      X
...
2018    A      X
1970    B      X
1971    B      X

etc...

I have tried the stack, and melt, and reshape functions to no avail. I also tried to list my data then flatten it, which was a total disaster. Any help is much appreciated!


Solution

  • We can use tidyverse

    library(dplyr)
    library(tidyr)
    df1 %>%
         pivot_longer(cols = -Year, values_to = 'Data') %>% 
        c
    # A tibble: 12 x 3
    #   Year  State Data 
    #   <chr> <chr> <chr>
    # 1 1970  A     X    
    # 2 1971  A     X    
    # 3 1972  A     X    
    # 4 1973  A     X    
    # 5 1970  B     X    
    # 6 1971  B     X    
    # 7 1972  B     X    
    # 8 1973  B     X    
    # 9 1970  C     X    
    #10 1971  C     X    
    #11 1972  C     X    
    #12 1973  C     X 
    

    Update

    With the updated example, change is

    df1 %>%
       pivot_longer(cols = -STATE, names_to = 'Year', values_to = 'Data')
    

    If package version of tidyr is old, use gather

    df1 %>%
        gather(name, Data, -Year) %>%
        separate(Year, into = c('other', 'State')) %>%
        select(Year = name, State, Data)
    

    Or with melt

    library(data.table)
    melt(setDT(df1), id.var = 'Year', value.name = 'Data')[, 
        .(State = sub('.*-', '', Year), Year = variable, Data)]
    

    data

    df1 <- structure(list(Year = c("State-A", "State-B", "State-C"), `1970` = c("X", 
    "X", "X"), `1971` = c("X", "X", "X"), `1972` = c("X", "X", "X"
    ), `1973` = c("X", "X", "X")), class = "data.frame", row.names = c(NA, 
    -3L))