如何按分组变量展开二进制变量并将数据集转为宽格式?
我懂你现在的困扰——想把长格式数据转成宽格式,每个ID单独占一行,而且DOB和Age这些每个ID唯一的信息只保留一列,同时把Outcome拆成多列,之前用tidyr或者reshape的时候还碰到了重复相关的报错对吧?别着急,咱们用tidyr的pivot_wider()就能完美解决这个问题,关键是要告诉函数怎么处理同一个ID下的多个Outcome值。
先给你模拟一份和你场景匹配的原始数据,方便你对照:
library(tidyr) library(dplyr) # 模拟你的长格式数据集 df <- tibble( ID = c(1,1,2,2,3), DOB = c("1990-01-01", "1990-01-01", "1985-05-05", "1985-05-05", "2000-10-10"), Age = c(34,34,39,39,24), Outcome = c("A", "B", "A", "C", "B") )
方案1:把多个Outcome转成带序号的列
如果你的每个ID对应多个不同的Outcome结果,想要把它们拆成Outcome_1、Outcome_2这样的列,可以先给每个ID下的Outcome加个序号,再转宽:
df_wide <- df %>% group_by(ID) %>% mutate(outcome_seq = row_number()) %>% # 给每个ID的Outcome按顺序编号 ungroup() %>% pivot_wider( id_cols = c(ID, DOB, Age), # 指定作为唯一标识的列(这些列每个ID只有唯一值) names_from = outcome_seq, values_from = Outcome, names_prefix = "Outcome_" # 给生成的列名加前缀 )
运行后你会得到每个ID一行,DOB和Age各一列,不同的Outcome分别放在带序号的列里。
方案2:把Outcome转成二进制指示列
如果你的Outcome是固定的几个类别(比如A、B、C),想要把每个类别变成单独的列,用1/0标记该ID是否有这个结果,可以这么写:
df_wide_binary <- df %>% pivot_wider( id_cols = c(ID, DOB, Age), names_from = Outcome, values_from = Outcome, values_fn = ~1, # 只要存在该Outcome就标记为1 values_fill = 0 # 不存在则填充0 )
这样生成的宽表会有A、B、C这类列,对应的值表示该ID是否有这个结果。
为什么之前会报错?
你之前碰到的重复相关错误,是因为默认情况下pivot_wider发现同一个ID(加上DOB、Age)对应多个Outcome值时,不知道该怎么聚合这些值。通过上面两种方式——要么给Outcome加序号让每个组合唯一,要么用values_fn指定聚合规则(比如标记存在与否),就能避免这个冲突啦。
内容的提问来源于stack exchange,提问作者user183974
相关产品推荐
相关产品推荐

