R语言:合并重复参与者行并按日期规整体重随访数据
解决重复行合并与按日期规整随访数据的方案
嗨,我太懂这种错位重复数据的头疼了!你之前用aggregate的方法会直接覆盖有效数据,肯定满足不了需求——咱们换用tidyverse工具链来处理,完美适配你要合并重复ID、按日期规整出勤和体重的需求,一步步来:
步骤1:把宽表转成长表(核心第一步)
首先把分散在多列的日期和体重数据转成“长格式”,这样方便我们统一处理所有出勤记录:
library(tidyverse) library(lubridate) # 假设你的原始数据框是df,包含participants_ID和date1-date20、weight1-weight20列 df_long <- df %>% pivot_longer( cols = -participants_ID, # 排除ID列,处理所有日期和体重列 names_to = c(".value", "original_week"), # 拆分列名:.value保留date/weight类型,original_week存原来的周数编号 names_pattern = "(date|weight)(\\d+)" # 用正则匹配列名里的类型和数字 ) %>% mutate(original_week = as.integer(original_week))
这一步会把每一行的多个日期/体重对拆成单独的行,比如p01的两行数据会变成4行有效记录(对应4次出勤)。
步骤2:清理并按日期排序数据
接下来去掉无效的NA记录,然后按参与者ID+出勤日期排序,再生成正确的顺序编号:
df_clean <- df_long %>% drop_na(date, weight) %>% # 去掉没有日期或体重的无效记录 arrange(participants_ID, date) %>% # 按ID分组,再按日期从早到晚排序 group_by(participants_ID) %>% mutate(correct_week = row_number()) # 为每个参与者的出勤记录生成正确的顺序号(1,2,3...)
这里的correct_week就是替换原来错误周数的关键,它会根据实际出勤日期重新排序编号。
步骤3:转回宽表,得到规整后的单行数据
最后把整理好的长表转回宽表,每个参与者就只有一行,日期和体重都按顺序排列:
df_final <- df_clean %>% pivot_wider( names_from = correct_week, # 用正确的顺序号作为列名后缀 names_glue = "{.value}{correct_week}", # 生成新列名:date1, date2... weight1, weight2... values_from = c(date, weight) # 对应填充日期和体重数据 ) %>% ungroup()
为什么你的aggregate方法不适用?
你之前用的aggregate(x = df, by = list(df$participants_ID), FUN = function(x) na.omit(x)[1]),本质是对每个ID的列取第一个非NA值,这会直接丢掉同一ID其他行的有效数据(比如p01重复行里的第5次出勤记录),而我们需要的是收集所有有效数据,再按日期重新排序规整,所以长表转宽表的思路才是正确的。
额外提示
如果你的日期列是字符格式,记得先转成日期类型,比如mutate(date = ymd(date))(根据你的日期格式调整lubridate的函数,比如mdy),这样排序才会准确。
内容的提问来源于stack exchange,提问作者jdt
相关产品推荐
相关产品推荐

