You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R中使用pivot_longer处理多列实现宽表转长表?

解决方案

首先修正原始数据中的笔误(di2_event_time应为dis2_event_time,否则无法正确匹配分组),然后使用pivot_longer的多列匹配功能一次性完成转换:

library(tidyverse)

# 修正列名后的原始数据
df = tribble(
  ~id, ~dis1_event, ~dis1_event_time, ~dis2_event, ~dis2_event_time,
  1,  1, '2022-01-01', 0, '2022-12-31',
  2, 0, '2018-01-01', 1, '2018-03-01',
)

# 宽转长的正确代码
df_result <- df %>%
  pivot_longer(
    cols = -id,  # 保留id列,转换其余所有列
    names_to = c("disease", ".value"),  # 拆分列名为两个部分:疾病标识,以及值对应的字段名
    names_pattern = "(dis\\d)_(.*)"  # 正则表达式捕获分组:第一组匹配dis1/dis2,第二组匹配event/event_time
  ) %>%
  rename(time = event_time)  # 将event_time重命名为time,匹配期望格式

# 验证结果与预期一致
all.equal(df_result, df_expected)
# [1] TRUE

关键逻辑说明

  1. names_to = c("disease", ".value"):names_to参数支持拆分列名为多个部分,其中.value是pivot_longer的特殊关键字,表示将第二部分捕获的内容作为新列名,同时把对应列的值填充到该列下。这能让dis1_event和dis1_event_time的值分别对应到event和event_time列,且归属同一个disease = "dis1"的分组。
  2. names_pattern正则匹配:(dis\\d)匹配dis1/dis2作为疾病标识,(.*)匹配后续的event或event_time作为字段类型,确保同一疾病的两列被分到同一组,不会出现错位。
  3. 重命名列:最后通过rename()把event_time改成time,和期望输出的列名完全一致。

为什么你的尝试失败?

连续两次调用pivot_longer会导致数据膨胀:第一次转换event列后,每个id生成2行数据;第二次转换time列时,每一行又会被拆成2行,最终得到8行数据,且disease列会出现重复和不匹配的情况,无法对应到正确的疾病-事件-时间组合。

内容的提问来源于stack exchange,提问作者zhiwei li

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 15:10:26