如何按ID重对齐数据集:将首次有效观测设为Time1并提取前6条
按个体首次有效观测值对齐时间序列数据
你需要将每个研究对象的首次有效观测作为Time1,依次取后续5个有效观测生成Time2-Time6,实现数据对齐。以下是基于R和Python的自动化解决方案,适用于大样本量场景:
原始示例数据
| ID | May | June | July | August | September | October | November | December | January | February |
|---|---|---|---|---|---|---|---|---|---|---|
| 1 | . | 34 | 36 | 72 | 89 | 23 | 10 | . | 10 | 16 |
| 2 | 22 | 34 | 36 | 72 | 89 | 23 | . | . | . | . |
| 3 | . | . | 36 | 72 | 89 | 23 | 45 | 80 | 15 | 12 |
期望输出
| ID | Time 1 | Time 2 | Time 3 | Time 4 | Time 5 | Time 6 |
|---|---|---|---|---|---|---|
| 1 | 34 | 36 | 72 | 89 | 23 | 10 |
| 2 | 22 | 34 | 36 | 72 | 89 | 23 |
| 3 | 36 | 72 | 89 | 23 | 45 | 80 |
R 实现(tidyverse 套件)
使用tidyr进行格式转换,dplyr进行分组过滤:
library(tidyverse) # 读取你的数据(替换为实际数据读取代码,比如read_csv()) df <- tibble( ID = c(1,2,3), May = c(NA,22,NA), June = c(34,34,NA), July = c(36,36,36), August = c(72,72,72), September = c(89,89,89), October = c(23,23,23), November = c(10,NA,45), December = c(NA,NA,80), January = c(10,NA,15), February = c(16,NA,12) ) # 核心处理逻辑 result <- df %>% # 宽格式转长格式,保留ID列 pivot_longer(cols = -ID, names_to = "Month", values_to = "Activity") %>% # 过滤缺失值(原始数据中的"."需先转为NA) filter(!is.na(Activity)) %>% # 按ID分组 group_by(ID) %>% # 取每个ID的前6个有效观测 slice_head(n = 6) %>% # 生成Time1-Time6的列名 mutate(Time = paste0("Time ", row_number())) %>% # 长格式转回宽格式 pivot_wider(names_from = Time, values_from = Activity) # 查看结果 print(result)
Python 实现(pandas 库)
利用pandas的 melt/dropna/groupby/pivot 方法完成转换:
import pandas as pd import numpy as np # 读取你的数据(替换为实际数据读取代码,比如pd.read_csv()) data = { 'ID': [1,2,3], 'May': [np.nan,22,np.nan], 'June': [34,34,np.nan], 'July': [36,36,36], 'August': [72,72,72], 'September': [89,89,89], 'October': [23,23,23], 'November': [10,np.nan,45], 'December': [np.nan,np.nan,80], 'January': [10,np.nan,15], 'February': [16,np.nan,12] } df = pd.DataFrame(data) # 核心处理逻辑 # 宽格式转长格式 df_long = df.melt(id_vars='ID', var_name='Month', value_name='Activity') # 过滤缺失值 df_long = df_long.dropna(subset=['Activity']) # 按ID分组,取前6个有效观测 df_top6 = df_long.groupby('ID').head(6) # 生成Time1-Time6列名 df_top6['Time'] = df_top6.groupby('ID').cumcount().apply(lambda x: f'Time {x+1}') # 转回宽格式并重置索引 result = df_top6.pivot(index='ID', columns='Time', values='Activity').reset_index() # 查看结果 print(result)
内容的提问来源于stack exchange,提问作者madrap
相关产品推荐
相关产品推荐

