简体   繁体   中英

Reshape data frame with no idvar - R

Suppose I have this data frame:

name <- rep(LETTERS[seq(from=1, to =2)], each=3)
MeasA <- c(1:6)
MeasB <- c(7:12)

df <- data.frame(name, MeasA, MeasB)

And I want to reshape into a format which has no idvar like this:

MeasA_A MeasB_A MeasB_B MeasB_B
 1        7        4      10
 2        8        5      11
 3        9        6      12

I have been reading about reshape and melt:

Reshaping data frame with duplicates

http://seananderson.ca/2013/10/19/reshape.html

But with those functions I need to specify an idvar. Ive tried:

tt <- reshape(df, timevar = "name", direction="wide")

and

tt <- dcast(df, ~name)

But they clearly dont work. Perhaps I need to use split ( Split data.frame based on levels of a factor into new data.frames ) then a reshape?

We could split the data.frame to list by the 'name' column, cbind the list elements. We can change the column names using sub or paste .

res <- do.call(cbind,split(df[-1], df$name))
colnames(res) <- sub('([^.]+)\\.([^.]+)', '\\2_\\1', colnames(res))
res
#  MeasA_A MeasB_A MeasA_B MeasB_B
#1       1       7       4      10
#2       2       8       5      11
#3       3       9       6      12

If we want to use dcast , we may need to create sequence column grouped by the 'name'. Here, I am using dcast from the devel version of 'data.table' ie v1.9.5 as it can take multiple value.var columns. Instructions to install the devel version are here . We convert the 'data.frame' to 'data.table' ( setDT(df) ), create the sequence column ('i1'), grouped by 'name', use dcast and specify the value.var columns.

library(data.table)#v1.9.5+
setDT(df)[, i1:= 1:.N, by = name]
dcast(df, i1~name, value.var=c('MeasA', 'MeasB'))[, i1:= NULL][]
#   MeasA_A MeasA_B MeasB_A MeasB_B
#1:       1       4       7      10
#2:       2       5       8      11
#3:       3       6       9      12

In a similar way we can use the reshape from base R . We create the sequence column using ave and use that as 'idvar in reshape`.

df1 <- transform(df, i1= ave(seq_along(name), name, FUN=seq_along))
reshape(df1, idvar='i1', timevar='name', direction='wide')[-1]
#  MeasA.A MeasB.A MeasA.B MeasB.B
#1       1       7       4      10
#2       2       8       5      11
#3       3       9       6      12

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM