2013-01-13 21 views
2

在我的分析的数据管理步骤中,我遇到了以下问题。分割时变量的值序列,有条件地编号

实际上,每个id被记录多达5次,并且我有一个感兴趣的时变变量,tv = 1, 2, 3, 4。假设我的数据是:

dat <- read.table(text = " 

     id  tv  
     1  2 
     1  2 
     1  1 
     1  4 
     2  4 
     2  1 
     2  4 
     3  1 
     3  2 
     3  3 
     3  3 
     3  2", 

    header=TRUE) 

我需要做的是创建两个新组从tv开始变量,以获得:

id  tv  tv1 tv2 tv3 tv4 tv5 dur1 dur2 dur3 dur4 dur5 
    1  2  2  1  4  0  0  2  1  1  0  0 
    1  2  2  1  4  0  0  2  1  1  0  0 
    1  1  2  1  4  0  0  2  1  1  0  0 
    1  4  2  1  4  0  0  2  1  1  0  0 
    2  4  4  1  4  0  0  1  1  1  0  0 
    2  1  4  1  4  0  0  1  1  1  0  0 
    2  4  4  1  4  0  0  1  1  1  0  0 
    3  1  1  2  3  2  0  1  1  2  1  0 
    3  2  1  2  3  2  0  1  1  2  1  0 
    3  3  1  2  3  2  0  1  1  2  1  0 
    3  3  1  2  3  2  0  1  1  2  1  0 
    3  2  1  2  3  2  0  1  1  2  1  0 

对于每个id,在tv1 - tv5我们具有的不同(非重复)记录的有序序列tv,而在dur1-dur5中,我们具有各个不同记录存在于原始数据中的次数等dat

我真的不知道如何在这里进行..任何帮助将不胜感激。

回答

3

这应做到:

require(plyr) 
dat <- structure(list(id = c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 
     3L, 3L), tv = c(2L, 2L, 1L, 4L, 4L, 1L, 4L, 1L, 2L, 3L, 3L, 2L 
     )), .Names = c("id", "tv"), class = "data.frame", row.names = c(NA, 
     -12L)) 

out <- ddply(dat, .(id), function(x) { 
    this.rle <- rle(x$tv) 

    val <- this.rle$values 
    val <- c(val, rep(0, 5-length(val))) 
    val <- matrix(rep(val,nrow(x)), byrow=T, nrow=nrow(x)) 
    val <- as.data.frame(val) 
    names(val) <- paste("tv", 1:5, sep="") 

    len <- this.rle$lengths 
    len <- c(len, rep(0, 5-length(len))) 
    len <- matrix(rep(len,nrow(x)), byrow=T, nrow=nrow(x)) 
    len <- as.data.frame(len) 
    names(len) <- paste("dur", 1:5, sep="") 
    cbind(data.frame(tv=x$tv), val, len) 
}) 

> out 
    id tv tv1 tv2 tv3 tv4 tv5 dur1 dur2 dur3 dur4 dur5 
1 1 2 2 1 4 0 0 2 1 1 0 0 
2 1 2 2 1 4 0 0 2 1 1 0 0 
3 1 1 2 1 4 0 0 2 1 1 0 0 
4 1 4 2 1 4 0 0 2 1 1 0 0 
5 2 4 4 1 4 0 0 1 1 1 0 0 
6 2 1 4 1 4 0 0 1 1 1 0 0 
7 2 4 4 1 4 0 0 1 1 1 0 0 
8 3 1 1 2 3 2 0 1 1 2 1 0 
9 3 2 1 2 3 2 0 1 1 2 1 0 
10 3 3 1 2 3 2 0 1 1 2 1 0 
11 3 3 1 2 3 2 0 1 1 2 1 0 
12 3 2 1 2 3 2 0 1 1 2 1 0 
+0

精彩!!非常感谢。 – Stezzo

+1

大量使用'rle()'。我对'plyr'不太熟悉,但我认为你可以简化一点,对吧?例如,我认为您不需要将矩阵转换为'data.frame',这样做肯定会增加处理时间。 – A5C1D2H2I1M1N2O1R2T1

+0

尽管这是一个很好的解决方案,并且以易于理解正在发生的事情的方式呈现。让我更加注意'plyr'! – A5C1D2H2I1M1N2O1R2T1

2

这里是完全在基地R的解决方案。它非常类似于@阿伦的回答,但很可能会快于使用“plyr”:

out <- cbind(dat, do.call(
    rbind, 
    lapply(split(dat$tv, dat$id), function(x) { 
     OUT <- matrix(0, ncol = 10, nrow = 1) 
     T1 <- rle(x) 
     OUT[1, seq_along(T1$values)] <- T1$values 
     OUT[1, 6:(5+length(T1$lengths))] <- T1$lengths 
     colnames(OUT) <- paste(rep(c("tv", "dur"), 
            each = 5), 1:5, sep ="") 
     OUT[rep(1, length(x)), ] 
    }))) 
out 
# id tv tv1 tv2 tv3 tv4 tv5 dur1 dur2 dur3 dur4 dur5 
# 1 1 2 2 1 4 0 0 2 1 1 0 0 
# 2 1 2 2 1 4 0 0 2 1 1 0 0 
# 3 1 1 2 1 4 0 0 2 1 1 0 0 
# 4 1 4 2 1 4 0 0 2 1 1 0 0 
# 5 2 4 4 1 4 0 0 1 1 1 0 0 
# 6 2 1 4 1 4 0 0 1 1 1 0 0 
# 7 2 4 4 1 4 0 0 1 1 1 0 0 
# 8 3 1 1 2 3 2 0 1 1 2 1 0 
# 9 3 2 1 2 3 2 0 1 1 2 1 0 
# 10 3 3 1 2 3 2 0 1 1 2 1 0 
# 11 3 3 1 2 3 2 0 1 1 2 1 0 
# 12 3 2 1 2 3 2 0 1 1 2 1 0 

这里发生的事情的总结:

  1. split(dat$tv, dat$id)创造价值的“电视”的清单每个“ID”。

  2. 我们采用了一个匿名函数中,我们:

    1. 创建零的一个空行矩阵。我们已经知道我们需要10列。
    2. 商店rle()输出,因为我们既需要“价值”和“长度”
    3. 使用基本的子集插入“值”到矩阵的前5列,且“长度”作为最后的五列。
    4. 添加列名
    5. 使用一些小技巧将矩阵“展开”到指定的行数,在这种情况下,行数与每组的行数相同。
  3. do.call(rbind...将所有矩阵放在一起,按行绑定它们。

  4. cbind(dat...结合原有data.frame从步骤1的结果为3

同样,在概念上,这是非常相似的Arun的答案 - 使用rle()是你失踪大概是什么。

+0

非常感谢,这两个答案都非常具有启发性。你说得对,你的脚本更快。 – Stezzo