【问题标题】:Complex long to wide data transformation (with time-varying variable)复杂的长到宽数据转换(具有时变变量)
【发布时间】:2012-12-27 03:24:50
【问题描述】:

我目前正在处理“长”形式的多状态分析数据集(每个人的观察一行;每个人最多重复测量 5 次)。

这个想法是每个人都可以在随时间变化的状态变量s = 1, 2, 3, 4的各个级别之间反复转换。我拥有的所有其他变量(此处为 cohort)都固定在任何给定的 id 内。

经过一些分析,我需要根据访问状态的特定顺序,以“宽”形式重塑数据集。下面是一个初始长数据的例子:

  dat <- read.table(text = "

        id    cohort    s    
        1       1       2
        1       1       2
        1       1       1
        1       1       4
        2       3       1
        2       3       1
        2       3       3
        3       2       1
        3       2       2
        3       2       3
        3       2       3
        3       2       4", 

    header=TRUE)     

最终的“宽”数据集应该考虑到访问状态的特定个体序列,记录到新创建的变量s1s2s3s4s5,其中@987654330 @ 是个人访问的第一个状态,依此类推。

根据上面的例子,宽数据集看起来像:

    id    cohort    s1    s2    s3    s4    s5    
    1       1       2      2     1     4     0
    2       3       1      1     3     0     0
    3       2       1      2     3     3     4

我尝试使用reshape(),并专注于转置s,但没有达到预期的效果。实际上,我对 R 函数的了解非常有限。你能给点建议吗?谢谢。

编辑:获取不同类型的宽数据集

谢谢大家的帮助,如果可以的话,我有一个相关的问题。尤其是当每个个体被长时间观察并且跨状态转换很少时,以这种替代方式重塑初始样本dat非常有用:

    id    cohort    s1    s2    s3    s4    s5    dur1  dur2  dur3  dur4  dur5 
    1       1       2      1     4     0     0      2     1     1     0     0  
    2       3       1      3     0     0     0      2     1     0     0     0
    3       2       1      2     3     4     0      1     1     2     1     0

实际上,现在s1-s5不同 访问状态,dur1-dur5 是在每个不同的访问状态中花费的时间。

你能帮我实现这个数据结构吗?我认为在使用reshape() 之前,有必要在中间样本中创建所有dur- 和s- 变量。不然可以直接采用-reshape2-吗?

【问题讨论】:

  • 基本上是direction = wide 选项,但我真的无法创建新的“有序”变量集..

标签: r reshape


【解决方案1】:

试试这个:

library(reshape2)

dat$seq <- ave(dat$id, dat$id, FUN = function(x) paste0("s", seq_along(x)))
dat.s <- dcast(dat, id + cohort ~ seq, value.var = "s", fill = 0)

这给出了这个:

> dat.s
  id cohort s1 s2 s3 s4 s5
1  1      1  2  2  1  4  0
2  2      3  1  1  3  0  0
3  3      2  1  2  3  3  4

如果您不介意仅使用 1、2、...、5 作为列名,则可以将 ave 行缩短为:

dat$seq <- ave(dat$id, dat$id, FUN = seq_along)

关于后面添加的第二个问题试试这个:

library(plyr)
dur.fn <- function(x) {
  r <- rle(x$s)$length
  data.frame(id = x$id[1], dur.value = r, dur.seq = paste0("dur", seq_along(r)))
}
dat.dur.long <- ddply(dat, .(id), dur.fn)
dat.dur <- dcast(dat.dur.long, id ~ dur.seq, c, value.var = "dur.value", fill = 0)
cbind(dat.s, dat.dur[-1])

给出:

  id cohort s1 s2 s3 s4 s5 dur1 dur2 dur3 dur4
1  1      1  2  2  1  4  0    2    1    1    0
2  2      3  1  1  3  0  0    2    1    0    0
3  3      2  1  2  3  3  4    1    1    2    1

【讨论】:

    【解决方案2】:
    dat <- read.table(text = "
            id    cohort    s    
            1       1       2
            1       1       2
            1       1       1
            1       1       4
            2       3       1
            2       3       1
            2       3       3
            3       2       1
            3       2       2
            3       2       3
            3       2       3
            3       2       4", 
        header=TRUE)     
    
    df <- data.frame(
        dat,
        period = sequence(rle(dat$id)$lengths) 
    )
    
    wide <- reshape(df, v.names = "s", idvar = c("id", "cohort"),
                    timevar = "period", direction = "wide")
    
    wide[is.na(wide)] = 0
    wide
    

    给予:

      id cohort s.1 s.2 s.3 s.4 s.5
    1  1      1   2   2   1   4   0
    5  2      3   1   1   3   0   0
    8  3      2   1   2   3   3   4
    

    然后使用以下行给出您的姓名:

    names(wide) <- c('id','cohort', paste('s', seq_along(1:5), sep=''))
    
    #   id cohort s1 s2 s3 s4 s5
    # 1  1      1  2  2  1  4  0
    # 5  2      3  1  1  3  0  0
    # 8  3      2  1  2  3  3  4
    

    如果在wide 语句中使用sep='',则不必重命名变量:

    wide <- reshape(df, v.names = "s", idvar = c("id", "cohort"),
                    timevar = "period", direction = "wide", sep='')
    

    我怀疑有一些方法可以避免创建period 变量并避免在wide 语句中直接替换NA,但我还没有弄清楚这些。

    【讨论】:

      【解决方案3】:

      好的...

      library(plyr)
      library(reshape2)
      
      dat2 <- ddply(dat,.(id,cohort), function(x) 
             data.frame(s=x$s,name=paste0("s",seq_along(x$s))))
      
      
      dat2 <- ddply(dat2,.(id,cohort), function(x) 
             dcast(x, id + cohort ~ name, value.var= "s" ,fill= 0)
             )
      
      dat2[is.na(dat2)] <- 0
      
      dat2
      
      #    id cohort s1 s2 s3 s4 s5
      #    1  1      1  2  2  1  4  0
      #    2  2      3  1  1  3  0  0
      #    3  3      2  1  2  3  3  4
      

      这看起来对吗?我承认第一个ddply 并不优雅。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多