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

R语言中按隔列规则重塑宽格式数据框的技术咨询

解决宽格式成对测试数据的整理问题

嘿,我太懂你现在的困扰了——这种把同一患者的多次测试用成对连续列存储的格式,处理起来确实很别扭。咱们直接用R里的tidyverse工具来把它转成更易用的长格式,一步到位!

首先先把你给出的示例数据明确下来,方便后续操作:

df1 <- data.frame(
  id = c("A","B"),
  test1 = c("10-12-16", "12-10-17"),
  test1_result = c("20", "3"),
  test2 = c("10-01-17", "11-12-17"),
  test2_result = c("18", "4"),
  test3 = c("12-03-18", NA),
  test3_result = c("15", "NA"),
  stringsAsFactors = FALSE
)

核心解决方案:用pivot_longer转长格式

tidyverse里的pivot_longer函数专门处理这种宽转长的场景,尤其是这种有规律的成对列名。咱们可以用正则表达式匹配列名里的测试编号,把日期和结果对应起来:

library(tidyverse)

df_long <- df1 %>%
  pivot_longer(
    cols = -id, # 除了id列之外的所有列都要转换
    names_to = c("test_number", ".value"), # 把列名拆成两部分:测试编号,以及值的类型(日期/结果)
    names_pattern = "test(\\d+)_(.*)|test(\\d+)" # 正则匹配:要么是testN_result,要么是testN
  ) %>%
  # 统一测试编号的列名(合并正则生成的两个临时列)
  mutate(test_number = coalesce(test_number, `test(\\d+)`)) %>%
  select(-`test(\\d+)`) %>%
  # 重命名日期列,让它更直观
  rename(test_date = test) %>%
  # 把结果转成数值型(按需选择)
  mutate(test_result = as.numeric(test_result))

运行完这段代码后,你得到的df_long就是标准的长格式了,每一行对应一个患者的一次测试记录,结构大概是这样:

# A tibble: 6 × 4
  id    test_number test_date test_result
  <chr> <chr>       <chr>           <dbl>
1 A     1           10-12-16           20
2 A     2           10-01-17           18
3 A     3           12-03-18           15
4 B     1           12-10-17            3
5 B     2           11-12-17            4
6 B     3           NA                  NA

额外说明

  • 如果你的测试列名有更复杂的规律,只需要调整names_pattern里的正则表达式就行,核心是把测试的标识和值的类型区分开。
  • 如果想过滤掉测试日期或结果为NA的记录,可以在管道最后加filter(!is.na(test_date), !is.na(test_result))。
  • 要是你还在使用旧版本的tidyverse,也可以用gather函数,但pivot_longer的可读性和灵活性更强,更推荐使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:28:53