[英]Complex long to wide data transformation (with time-varying variable)
I am currently working on a Multistate Analysis dataset in "long" form (one row for each individual's observation; each individual is repeatedly measured up to 5 times). 我目前正在处理“长”格式的多状态分析数据集(每个人的观察结果一行;每个人被重复测量多达5次)。
The idea is that each individual can recurrently transition across the levels of the time-varying state variable s = 1, 2, 3, 4
. 这个想法是,每个人都可以在时变状态变量
s = 1, 2, 3, 4
的级别上反复转换。 All the other variables that I have (here cohort
) are fixed within any given id
. 我全部的(这里的其他变量
cohort
)固定任何给定的范围内id
。
After some analyses, I need to reshape the dataset in "wide" form, according to the specific sequence of visited states. 经过一些分析后,我需要根据访问状态的特定顺序以“宽”形式重整数据集。 Here is an example of the initial long data:
这是初始长数据的示例:
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)
The final "wide" dataset should take into account the specific individual sequence of visited states, recorded into the newly created variables s1
, s2
, s3
, s4
, s5
, where s1
is the first state visited by the individual and so on. 最终的“宽”数据集应考虑被访问状态的特定个体序列,并记录到新创建的变量
s1
, s2
, s3
, s4
, s5
,其中s1
是个人访问的第一个状态,依此类推。
According to the above example, the wide dataset looks like: 根据上面的示例,宽数据集看起来像:
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
I tried to use reshape()
, and also to focus on transposing s
, but without the intended result. 我尝试使用
reshape()
,也专注于转置s
,但是没有达到预期的结果。 Actually, my knowledge of the R functions is quite limited.. Can you give any suggestion? 实际上,我对R函数的了解非常有限。您能提出任何建议吗? Thanks.
谢谢。
Thank you all for your help, I have a related question if I can. 谢谢大家的帮助,如果可以的话,我有一个相关的问题。 Especially when each individual is observed for a long time and there are few transitions across states, it is very useful to reshape the initial sample
dat
in this alternative way: 尤其是长时间观察每个个体并且状态之间的转换很少时,以这种替代方式重塑初始样本
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
In practice now s1
- s5
are the distinct visited states, and dur1
- dur5
the time spent in each respective distinct visited state. 实际上,现在
s1
- s5
是不同的访问状态,而dur1
- dur5
是在每个相应的不同访问状态中花费的时间。
Can you please give a hand for reaching this data structure? 您能帮忙实现此数据结构吗? I believe it is necessary to create all the
dur
- and s
- variables in an intermediate sample before using reshape()
. 我相信有必要在使用
reshape()
之前在中间样本中创建所有dur
和s
变量。 Otherwise maybe it is possible to directly adopt -reshape2-
? 否则,可以直接采用
-reshape2-
吗?
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
Gives: 给出:
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
then using the following line gives your names: 然后使用以下行给出您的名字:
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
If you use sep=''
in the wide
statement you do not have to rename the variables: 如果在
wide
语句中使用sep=''
,则不必重命名变量:
wide <- reshape(df, v.names = "s", idvar = c("id", "cohort"),
timevar = "period", direction = "wide", sep='')
I suspect there are ways to avoid creating the period
variable and avoid replacing NA
directly in the wide
statement, but I have not figured those out yet. 我怀疑有很多方法可以避免创建
period
变量,并且可以避免在wide
语句中直接替换NA
,但是我还没有找到解决方法。
ok... 好...
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
This seem right? 这看起来对吗? I admit the first
ddply
is hardly elegant. 我承认第一个
ddply
不太优雅。
Try this: 尝试这个:
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)
which gives this: 这给出了:
> 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
If you did not mind using just 1, 2, ..., 5 as column names then you could shorten the ave
line to just: 如果您不介意仅使用1、2,...,5作为列名,则可以将
ave
行缩短为:
dat$seq <- ave(dat$id, dat$id, FUN = seq_along)
Regarding the second question that was added later try this: 关于稍后添加的第二个问题 ,请尝试以下操作:
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])
which gives: 这使:
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.