[英]Complex long to wide data transformation (with time-varying variable)
我目前正在處理“長”格式的多狀態分析數據集(每個人的觀察結果一行;每個人被重復測量多達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)
最終的“寬”數據集應考慮被訪問狀態的特定個體序列,並記錄到新創建的變量s1
, s2
, s3
, s4
, s5
,其中s1
是個人訪問的第一個狀態,依此類推。
根據上面的示例,寬數據集看起來像:
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-
嗎?
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
,但是我還沒有找到解決方法。
好...
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
不太優雅。
嘗試這個:
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.