从宽到长重塑调查数据集
reshape survey data set from wide to long
我有这样一个调查数据集:
df <- data.frame(
employment = 0.45,
income = 0.3,
incomeFU1 = 0.4,
married = 0.1,
employmentFU1 = 0.7,
employmentFU2 = 0.8,
incomeFU2 = 0.8,
smokingFU1 = 0.6,
smokingFU3 = 0.1,
ageFU3 = 0.9,
marriedFU2 = 0.3
)
在这个数据集中,个人被问及他们的就业状况、收入等。
数据是一个综合水平,将其视为就业人口的比例,平均收入等。因此数据集只有一行。
本次调查中的个人在基线和 3 次跟进时被问及。
基线变量没有结尾字符串,后续答案的结尾类似于 "FU1" 后续 1 等等。
我现在有了这些变量的第二个列表:
l <- list()
l[[1]] <- c("employment", "income", "married")
l[[2]] <- c("employmentFU1", "incomeFU1", "smokingFU1")
l[[3]] <- c("employmentFU2", "incomeFU2", "marriedFU2")
l[[4]] <- c("smokingFU3", "ageFU3")
第一个列表项有基线变量,第二个列表项有后续 1 个变量,第三个有后续 2 等
请注意,一些变量在 2 次或 3 次(有时甚至全部)后续行动中可用,有些只出现一次。
我现在想根据列表变量将此数据框重塑为矩阵或数据框,如下所示:
employment income married NA NA
employmentFU1 incomeFU1 NA smokingFU1 NA
employmentFU2 incomeFU2 marriedFU2 NA NA
NA NA NA smokingFU3 ageFU3
这个矩阵中的行数是列表元素的数量,在本例中是 4。
我试过这样的东西,但没有走得太远:
m <- matrix()
m[1,1] <- df[, l[[1]][1]]
m[1,2] <- l[[2]][str_detect(l[[1]][1], l[[2]])]
这就是我尝试使用 stringr
解决该问题的方法。可能存在更有效的方法
library(stringr)
table <- str_match(unlist(l), "(.*?)($|FU[0-9]+?)")
table[table==""] <- "FU0" ## "" is problematic
m <- matrix(NA, length(unique(table[,3])), length(unique(table[,2])))
colnames(m) <- unique(table[,2])
rownames(m) <- unique(table[,3])
foo <- apply(table, 1, function(row) m[row[3],row[2]] <<- row[1])
print(m)
# employment income married smoking age
#FU0 "employment" "income" "married" NA NA
#FU1 "employmentFU1" "incomeFU1" NA "smokingFU1" NA
#FU2 "employmentFU2" "incomeFU2" "marriedFU2" NA NA
#FU3 NA NA NA "smokingFU3" "ageFU3"
我有这样一个调查数据集:
df <- data.frame(
employment = 0.45,
income = 0.3,
incomeFU1 = 0.4,
married = 0.1,
employmentFU1 = 0.7,
employmentFU2 = 0.8,
incomeFU2 = 0.8,
smokingFU1 = 0.6,
smokingFU3 = 0.1,
ageFU3 = 0.9,
marriedFU2 = 0.3
)
在这个数据集中,个人被问及他们的就业状况、收入等。 数据是一个综合水平,将其视为就业人口的比例,平均收入等。因此数据集只有一行。
本次调查中的个人在基线和 3 次跟进时被问及。 基线变量没有结尾字符串,后续答案的结尾类似于 "FU1" 后续 1 等等。
我现在有了这些变量的第二个列表:
l <- list()
l[[1]] <- c("employment", "income", "married")
l[[2]] <- c("employmentFU1", "incomeFU1", "smokingFU1")
l[[3]] <- c("employmentFU2", "incomeFU2", "marriedFU2")
l[[4]] <- c("smokingFU3", "ageFU3")
第一个列表项有基线变量,第二个列表项有后续 1 个变量,第三个有后续 2 等
请注意,一些变量在 2 次或 3 次(有时甚至全部)后续行动中可用,有些只出现一次。
我现在想根据列表变量将此数据框重塑为矩阵或数据框,如下所示:
employment income married NA NA
employmentFU1 incomeFU1 NA smokingFU1 NA
employmentFU2 incomeFU2 marriedFU2 NA NA
NA NA NA smokingFU3 ageFU3
这个矩阵中的行数是列表元素的数量,在本例中是 4。
我试过这样的东西,但没有走得太远:
m <- matrix()
m[1,1] <- df[, l[[1]][1]]
m[1,2] <- l[[2]][str_detect(l[[1]][1], l[[2]])]
这就是我尝试使用 stringr
解决该问题的方法。可能存在更有效的方法
library(stringr)
table <- str_match(unlist(l), "(.*?)($|FU[0-9]+?)")
table[table==""] <- "FU0" ## "" is problematic
m <- matrix(NA, length(unique(table[,3])), length(unique(table[,2])))
colnames(m) <- unique(table[,2])
rownames(m) <- unique(table[,3])
foo <- apply(table, 1, function(row) m[row[3],row[2]] <<- row[1])
print(m)
# employment income married smoking age
#FU0 "employment" "income" "married" NA NA
#FU1 "employmentFU1" "incomeFU1" NA "smokingFU1" NA
#FU2 "employmentFU2" "incomeFU2" "marriedFU2" NA NA
#FU3 NA NA NA "smokingFU3" "ageFU3"