2
votes

I have an R data frame like this with one factor variable, and two or more value variables.

> factorvar <- c('a', 'b', 'c')
> valvar1 <- c(1, 1, 1)
> valvar2 <- c(2, 2, 2)
> df <- data.frame(factorvar, valvar1, valvar2)
> df
  factorvar valvar1 valvar2
1         a       1       2
2         b       1       2
3         c       1       2

I want to widen it such that the final data frame looks something like the following:

> dfnew
  valvar1.a valvar1.b valvar1.c valvar2.a valvar2.b valvar2.c
  1         1         1         1         2         2         2

dplyr/tidyr with spread only allow me to do it for one column (value).

2
Melt/gather first so it's fully long, then dcast/spread.Gregor Thomas

2 Answers

3
votes

This solution uses the dplyr and tidyr libraries:

library(dplyr)
library(tidyr)

df %>%
  gather(valvar, value, -factorvar) %>%
  unite(key, factorvar, valvar) %>%
  mutate(dummy = 1) %>%
  spread(key, value) %>%
  select(-dummy)

Which returns:

  a_valvar1 a_valvar2 b_valvar1 b_valvar2 c_valvar1 c_valvar2
1         1         2         1         2         1         2
1
votes

Try dcast from the devel version of data.table i.e. v1.9.5. This can take multiple value columns, so you may not need to change the format to long. It can be installed from here

 library(data.table)
 dcast(setDT(df)[,ind:=1:.N, by = factorvar], ind~factorvar, 
              value.var=c('valvar1', 'valvar2')) 
 #    ind a_valvar1 b_valvar1 c_valvar1 a_valvar2 b_valvar2 c_valvar2
 #1:   1         1         1         1         2         2         2

Or a more compact option by @Arun

 dcast(setDT(df), . ~ factorvar, value.var=c("valvar1", "valvar2"))