在我的分析的数据管理步骤中,我遇到了以下问题。
在实践中,每个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
中各自不同记录的出现次数。
我真的不知道如何继续这里..任何帮助将不胜感激。
答案 0 :(得分: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
答案 1 :(得分:2)
这是一个完全基于R的解决方案。它与@ Arun的答案非常相似,但可能比使用“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
以下是对正在发生的事情的总结:
split(dat$tv, dat$id)
为每个“id”在“tv”中创建一个值列表。
我们应用匿名函数:
rle()
的输出,因为我们需要“值”和“长度” do.call(rbind...
将所有矩阵放在一起,按行绑定它们。
cbind(dat...
将原始data.frame
绑定到步骤1到3的结果。
同样,从概念上讲,这与Arun的回答非常相似 - rle()
的使用可能就是你所缺少的。