wide to long multiple measures each time

后端 未结 5 1360
慢半拍i
慢半拍i 2020-12-01 06:45

I know the wide to long has been asked way too many times on here but I can\'t figure out how to turn the following into long format. Shoot I even asked one of the wide to

相关标签:
5条回答
  • 2020-12-01 07:19

    Oddly enough I don't seem to get the same numbers as you (which I should since we both used set.seed(10)?) but otherwise this seems to do the trick:

    library(reshape)  #this might work with reshape2 as well, I haven't tried ...
    DF2 <- melt(DF,id.vars=1:2)
    ## split 'activity.time' label into two separate variables
    DF3 <- cbind(DF2,
                 colsplit(as.character(DF2$variable),"\\.",
                          names=c("activity","time")))
    ## rename time, reorder factors:
    DF4 <- transform(DF3,
                     time=as.numeric(gsub("^T","",time)),
                     activity=factor(activity,
                       levels=c("work","play","talk","total")),
                     id=factor(id,levels=paste("x1",1:10,sep=".")))
    ## reshape back to wide
    DF5 <- cast(subset(DF4,select=-variable),id+trt+time~activity)
    ## reorder
    DF6 <- with(DF5,DF5[order(time,id),])
    

    It's more complicated than @DWin's answer but maybe (?) more general.

    0 讨论(0)
  • 2020-12-01 07:19

    Another way to approach the problem that requires very little code but would likely be slower,:

    DF.1 <- DF[, 1:2]
    DF.2 <- DF[, 3:6] 
    DF.3 <- DF[, 7:10]
    
    names(DF.2) <- names(DF.3) <- unlist(strsplit(names(DF.2), ".", fixed=T))[c(T,F)]
    time <- rep(1:2, each=nrow(DF.1))
    data.frame(rbind(DF.1, DF.1), time, rbind(DF.2, DF.3))
    
    0 讨论(0)
  • 2020-12-01 07:25

    If you really didn't want the "T" in the "time" variable in the output, couldn't you simply do the following?

    names(DF) = sub("T", "", names(DF))
    reshape(DF, direction="long", varying=3:10)
    

    Or, without changing names(DF), you could simply set the sep= argument to include "T":

    reshape(DF, direction="long", varying=3:10, sep=".T")
    

    I'm a bit confused, though. As Ben Bolker pointed out a in his comment, your "dataset code" doesn't provide the same numbers as what you have. Also, the output of DWin and mine matches perfectly, but it does not match with the "into this" output that you have in your original question.

    I checked this by creating one data frame named "DWin" with his results, and one data frame named "mine" with my results and compared them using DWin == mine.

    Can you verify that the output we've gotten is actually what you needed?

    0 讨论(0)
  • 2020-12-01 07:38

    This is pretty close and changing the names of columns should be within your skillset:

    reshape(DF, 
           varying=c(work= c(3, 7), play= c(4,8), talk= c(5,9), total= c(6,10) ), 
           direction="long")
    

    EDIT: Adding a version that is almost an exact solution:

    reshape(DF, varying=list(work= c(3, 7), play= c(4,8), talk= c(5,9), total= c(6,10) ), 
            v.names=c("Work", "Play", "Talk", "Total"), 
              # that was needed after changed 'varying' arg to a list to allow 'times' 
            direction="long",  
            times=1:2,        # substitutes number for T1 and T2
            timevar="times")  # to name the time col
    
    0 讨论(0)
  • 2020-12-01 07:42

    The most concise way is to use tidyr combined with dplyr library.

    library(tidyr)
    library(dplyr)
    result <- DF %>%
      # transfer to 'long' format
      gather(loc, value, work.T1:total.T2) %>%
      # separate the column into location and time
      separate(loc, into = c('loc', 'time'), '\\.') %>%
      # transfer to 'short' format
      spread(loc, value) %>%
      mutate(time = as.numeric(substr(time, 2, 2))) %>%
      arrange(time)
    

    tidyr is designed specifically to make data tidy.

    0 讨论(0)
提交回复
热议问题