嵌套重复测量数据集的多列变量整合技术咨询
嘿,这个问题我太熟了!在家庭嵌套的重复测量数据里,这种按受访者类型拆分变量列的情况真的很常见,咱们用tidyverse工具就能轻松搞定。先给你理清楚思路,再上代码示例~
首先,先明确咱们的目标:把分散在多列的同一名义变量(比如v1的v1_a/v1_b/v1_c)合并成一列,同时保留嵌套(家庭-个人)和重复测量(time)的结构,最终形成每行对应一个个体-时间点的整洁数据集。
先构造个示例数据集(方便你对应自己的真实数据)
我先模拟一个和你描述一致的数据集,包含家庭ID、个人ID、类型、时间,以及三类分散的变量:
library(tidyverse) set.seed(123) # 固定随机种子,方便复现 df <- tibble( hid = rep(1:2, each = 3*2), # 2个家庭,每个家庭3个成员,2次测量 time = rep(1:2, each = 3, times = 2), pid = rep(c("1a", "1b", "1c", "2a", "2b", "2c"), each = 2), type = rep(c("a", "b", "c"), times = 4), # 全类型变量:v1分三列,对应a/b/c三类 v1_a = ifelse(type == "a", rnorm(12), NA), v1_b = ifelse(type == "b", rnorm(12), NA), v1_c = ifelse(type == "c", rnorm(12), NA), # 部分类型变量:v2仅a/b类有,分两列 v2_a = ifelse(type == "a", rnorm(12), NA), v2_b = ifelse(type == "b", rnorm(12), NA), # 单类型变量:v3仅c类有,单独一列 v3_c = ifelse(type == "c", rnorm(12), NA) )
分步处理不同类型的变量
1. 处理全类型覆盖的变量(比如v1)
这类变量每个类型都对应一列,我们可以用pivot_longer提取变量名里的类型标识,再和数据里的type列匹配,过滤掉无关的NA值:
# 处理全类型变量v1 df_v1 <- df %>% select(hid, time, pid, type, starts_with("v1_")) %>% # 只保留相关列 pivot_longer( cols = starts_with("v1_"), names_to = c("var", "var_type"), # 拆分列名为变量名和类型 names_pattern = "(v1)_(.)", # 用正则匹配"v1_a"里的v1和a values_to = "value" ) %>% filter(type == var_type) %>% # 只保留和当前个体类型匹配的数值 select(-var_type) %>% # 去掉临时的类型列 pivot_wider(names_from = var, values_from = value) # 转回宽格式,得到v1列
2. 处理仅部分类型覆盖的变量(比如v2)
逻辑和上面完全一致,只是变量列只有a/b两类,过滤后自然会保留对应个体的数值,其他类型的v2会是NA(符合实际情况):
# 处理部分类型变量v2 df_v2 <- df %>% select(hid, time, pid, type, starts_with("v2_")) %>% pivot_longer( cols = starts_with("v2_"), names_to = c("var", "var_type"), names_pattern = "(v2)_(.)", values_to = "value" ) %>% filter(type == var_type) %>% select(-var_type) %>% pivot_wider(names_from = var, values_from = value)
3. 处理仅单类型覆盖的变量(比如v3)
这类最简单,直接重命名列即可,其他类型的行自然会保留NA,不用额外过滤:
# 处理单类型变量v3 df_v3 <- df %>% select(hid, time, pid, type, v3_c) %>% rename(v3 = v3_c) # 把v3_c重命名为v3
合并所有处理后的数据集
最后把基础标识列和所有处理好的变量列合并,就得到了整洁的数据集:
# 合并所有表,基于家庭、时间、个人、类型匹配 final_df <- df %>% select(hid, time, pid, type) %>% # 保留核心标识列 left_join(df_v1, by = c("hid", "time", "pid", "type")) %>% left_join(df_v2, by = c("hid", "time", "pid", "type")) %>% left_join(df_v3, by = c("hid", "time", "pid", "type")) # 查看处理后的结果 head(final_df)
额外小技巧
- 如果有多个同类型的变量(比如v1、v4都是全类型覆盖),可以用
map函数批量处理,不用重复写代码。 - 如果你的变量名格式不是
var_type(比如是v1dad而不是v1_a),只需要调整names_pattern的正则表达式,比如改成names_pattern = "(v1)([a-c])"就能匹配。 - 处理后的数据集完全符合tidy data标准,后续不管做描述性统计还是混合效应模型(比如lme4)都非常方便。
内容的提问来源于stack exchange,提问作者Eric Green
相关产品推荐
相关产品推荐

