2013-01-13 22 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