3

I am trying to add a time-varying predictor to a long-form dataframe using reshape2::melt but I was wondering if there was a faster way to do it.

Here is the toy data in wide form. There are three measures of an outcome variable (session1, session2, and session3) taken at different visits/time points. The duration between these three visits is different for each participant and ultimately I would like to factor these differences into a model.

id <- 1:10
group <- rep(c("A", "B"), times = 5)
session1 <- rnorm(10, 5, 1)
session2 <- rnorm(10, 3, 1)
session3 <- rnorm(10, 7, 2)
time1 <- rep(0, 10)
time2 <- rnorm(10, 24, 0.5)
time3 <- rnorm(10, 48, 0.5)

df <- data.frame(id, group, session1, session2, session3, time1, time2, time3)

Now I want to convert into a long-form dataframe. I use reshape2::melt. I can create this either around the scores like so:

library(reshape2)
dfLong <- melt(df, measure.vars = c("session1", "session2", "session3"), var = "session", value.name = "score")

Or I can create it around the time values.

dfLong2 <- melt(df, measure.vars = c("time1", "time2", "time3"), var = "time", value.name = "timeOut")

But I can't do both without doing the melt twice and performing some sort of opertation like this

dfLong$timeOut <- dfLong2$timeOut

Ultimately I would like the dataframe to look something like this

dfLong$time <- rep(c("time1", "time2", "time3"), each = 10)

dfLong <- dfLong[,which(names(dfLong) %in% c("id", "group", "time", "session", "score", "timeOut"))]

dfLong

Is there any way to melt two sets of columns at once?

Frank
  • 66,179
  • 8
  • 96
  • 180
llewmills
  • 2,959
  • 3
  • 31
  • 58
  • 4
    `reshape(df, dir = 'long', varying = lapply(c('session', 'time'), grep, names(df)))` – rawr Jun 17 '16 at 15:25
  • 2
    http://stackoverflow.com/questions/37756389/r-convert-multiple-columns-into-single-column or http://stackoverflow.com/questions/12466493/mapping-multiple-sets-of-columns-into-single-columns-with-reshape-melt-recast-in – rawr Jun 17 '16 at 15:26

1 Answers1

4

We can use data.table

library(data.table)
res = melt(setDT(df), measure = patterns("^session", "^time"), 
                           value.name = c("session", "time"))

You can setDF(res) to revert to a data.frame if you don't want to learn how to work with data.tables right now.

Frank
  • 66,179
  • 8
  • 96
  • 180
akrun
  • 874,273
  • 37
  • 540
  • 662