0

Consider I have a data frame in long format with three columns. Column x contains the measurements, y the names of the 3 variables, and z contains 2 levels. There are duplicate measurements for each of the y variables:

df <- data.frame(x=c(1:12), y=rep(0:2, 4), z=rep(letters[1:2], 6))
df$y <- as.factor(df$y)
df <- arrange(df, y, z)
df

    x y z
1   1 0 a
2   7 0 a
3   4 0 b
4  10 0 b
5   5 1 a
6  11 1 a
7   2 1 b
8   8 1 b
9   3 2 a
10  9 2 a
11  6 2 b
12 12 2 b

How can I get df_wide like this?

z  0  1  2
a  1  5  3
a  7  11 9
b  4  2  6
b  10 8  12
Uwe
  • 41,420
  • 11
  • 90
  • 134
datanew
  • 279
  • 3
  • 14
  • can you elaborate what is going on here? – mtoto Sep 13 '17 at 19:40
  • In df, column-x is the measurements, column-y is the 3 variables, column-z contains 2 levels, and each has duplicate measurements for the column-y variables. Hope that's clear:) Thank you@mtoto – datanew Sep 13 '17 at 19:51

2 Answers2

1
do.call(cbind, lapply(split(df, df$y), function(a)
    setNames(object = data.frame(a$x,
                                 row.names = paste0(as.character(a$z), 1:NROW(a))),
             nm = a$y[1])))
#    0  1  2
#a1  1  5  3
#a2  7 11  9
#b3  4  2  6
#b4 10  8 12
d.b
  • 32,245
  • 6
  • 36
  • 77
  • Thank you! @d.b Actually, I have a list of dfs. This df is one element of my list. How can I implement the do.call(...) code in the list? – datanew Sep 13 '17 at 20:04
1

Using the dcast() and rowid() functions from the data.table package this becomes a "one-liner":

library(data.table)
dcast(setDT(df), paste0(z, rowid(y, z)) ~ y, value.var = "x")
    z  0  1  2
1: a1  1  5  3
2: a2  7 11  9
3: b1  4  2  6
4: b2 10  8 12
Uwe
  • 41,420
  • 11
  • 90
  • 134