R语言使用pivot_wider实现含多值字段的长表转宽表
核心处理逻辑
- 先给每行数据归属到对应ID分组,解决原始数据ID与属性行纵向排列的对应问题
- 统一属性名(去掉
col1字段末尾的多余点号),避免同一属性被识别为不同类别 - 对同一ID下的多个
animal值生成递增序号,其余属性仅保留单序列 - 执行长转宽操作,缺失值自动填充NA
R 实现(基于tidyverse工具链)
library(tidyverse) # 预处理:归属ID分组、统一属性名 df_clean <- df %>% mutate( # 生成ID分组:遇到ID行取对应值,其余行向前填充最近的ID ID = if_else(col1 == "ID", col2, NA_character_) %>% zoo::na.locf(), # 去掉col1末尾的点,统一属性命名 col1 = str_remove(col1, "\\.$") ) %>% # 过滤掉原始ID行,避免重复计数 filter(col1 != "ID") # 给同ID下的animal生成序号 df_clean <- df_clean %>% group_by(ID, col1) %>% mutate(idx = if_else(col1 == "animal", row_number(), 1)) %>% ungroup() # 长转宽 df_wide <- df_clean %>% pivot_wider( id_cols = ID, names_from = c(col1, idx), values_from = col2, names_sep = "" )
Python 实现(基于pandas)
import pandas as pd import numpy as np # 预处理:归属ID分组、统一属性名 df['ID'] = np.where(df['col1'] == 'ID', df['col2'], np.nan) df['ID'] = df['ID'].ffill() # 去掉col1末尾的点,统一属性命名 df['col1'] = df['col1'].str.rstrip('.') # 过滤掉原始ID行 df = df[df['col1'] != 'ID'].reset_index(drop=True) # 给同ID下的animal生成序号 df['idx'] = df.groupby(['ID', 'col1']).cumcount() + 1 # 非animal属性无需生成多列,序号统一为1 df.loc[df['col1'] != 'animal', 'idx'] = 1 # 长转宽 df_wide = df.pivot( index='ID', columns=['col1', 'idx'], values='col2' ).reset_index() # 合并列名,非animal列去掉序号后缀 df_wide.columns = [f"{col}{num}" if num != 1 else col for col, num in df_wide.columns]
内容的提问来源于stack exchange,提问作者alex
相关产品推荐
相关产品推荐

