Complex data reshaping in R

Try

library(dplyr)
library(tidyr) 
gather(df, Var, Val, -Year) %>% 
        unite(YearVar, Var, Year)  %>% 
        mutate(indx=1) %>% 
        spread(YearVar, Val)%>%
        select(-indx)
 #  A_2007 A_2008 A_2009 B_2007 B_2008 B_2009
 #1      5      2      3     10      0     50

Update

For the edit, you can change the variables in the gather

gather(df, Var, Val, A:B) %>% 
         unite(YearVar, Var, Year) %>% 
         spread(YearVar, Val)
#   id A_2007 A_2008 A_2009 B_2007 B_2008 B_2009
#1  1      5      2      3     10      0     50
#2  2      7      5      6     13     17     17

Here's a possible solution using data.table v >= 1.9.5

library(data.table)
dcast(setDT(df), . ~ Year, value.var = c("A", "B"))
#    . 2007_A 2008_A 2009_A 2007_B 2008_B 2009_B
# 1: .      5      2      3     10      0     50

Edit: per your new data set, simply add id to the formula

dcast(setDT(df), id ~ Year, value.var = c("A", "B"))
#    id 2007_A 2008_A 2009_A 2007_B 2008_B 2009_B
# 1:  1      5      2      3     10      0     50
# 2:  2      7      5      6     13     17     17

Good ol' base::reshape works fine here. Just create a dummy id variable first.

df$id <- 1
reshape(df, v.names = c("A", "B"), timevar = "Year", idvar = "id", direction = "wide")
#   id A.2007 B.2007 A.2008 B.2008 A.2009 B.2009
# 1  1      5     10      2      0      3     50

To save some typing, given that you specify timevar and idvar, you don't have to provide v.names:

reshape(df, timevar = "Year", idvar = "id", direction = "wide")

This works for the edited data as well (which happened to have the "id" variable already).

#    id A_2007 B_2007 A_2008 B_2008 A_2009 B_2009
#  1  1      5     10      2      0      3     50
#  2  2      7     13      5     17      6     17

You may also use reshape2::recast:

recast(df, id ~ variable + Year, id.var = 1:2)

Tags:

R

Reshape2

Tidyr