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

如何用pivot_longer处理变量命名不一致的宽表转长表?

解决变量名格式不一致的宽表转长表问题

针对你遇到的变量名后缀编号不统一、变量组长度不同的情况,可以通过「先转基础长表→提取变量组与编号→再转宽」的流程实现目标,具体代码如下:

完整处理代码

library(tidyr)
library(dplyr)

# 生成示例数据(你已有的代码)
set.seed(1234)
m <- matrix(sample(1:10, 75, replace = T), 5, 15)
id <- 1:5
d <- cbind(id, as.data.frame(m))
names(d) <- c("id", "X1_hg", "X1_hg2", "X1_hg3", "X1_hg4", "cuphg_m01", 
              "cuphg_m02", "cuphg_m03", "cuphg_m04", "cuphg_m05", "cuphg_v01",
              "cuphg_v02", "cuphg_v03", "cuphg_v04", "cuphg_v05", "cuphg_v06")

# 宽转长核心流程
d_target <- d %>%
  # 第一步:将所有非id列转为基础长表
  pivot_longer(-id, names_to = "var_name", values_to = "value") %>%
  # 第二步:提取变量组前缀和index编号
  mutate(
    var_group = case_when(
      str_starts(var_name, "X1_hg") ~ "X1_hg",
      str_starts(var_name, "cuphg_m") ~ "cuphg_m",
      str_starts(var_name, "cuphg_v") ~ "cuphg_v"
    ),
    index = case_when(
      # X1_hg系列:无数字后缀的对应index=1,否则取末尾数字
      str_starts(var_name, "X1_hg") ~ ifelse(var_name == "X1_hg", "1", str_extract(var_name, "\\d+$")),
      # cuphg_m/v系列:去掉前缀和前导零,提取数字
      str_starts(var_name, "cuphg_m") ~ str_remove(var_name, "cuphg_m0?"),
      str_starts(var_name, "cuphg_v") ~ str_remove(var_name, "cuphg_v0?")
    ) %>% as.integer()
  ) %>%
  # 第三步:将变量组转为列,得到目标结构
  pivot_wider(names_from = var_group, values_from = value) %>%
  # 按id和index排序(可选)
  arrange(id, index)

关键步骤说明

  1. 基础长表转换:先用pivot_longer(-id)把所有非id列转为var_name(变量名)和value(变量值)的长表结构,统一处理变量名。
  2. 提取变量组与编号:
    • 用case_when根据变量名前缀区分三组变量;
    • 针对不同变量名格式单独提取index:X1_hg系列无后缀的对应index=1,cuphg_m/v系列去掉前导零后提取数字编号。
  3. 转宽得到目标结构:用pivot_wider将变量组转为列,不同长度的变量组会自动用NA填充缺失值,符合你的需求。

通用优化方案(多变量组场景)

如果你的实际数据有更多变量组,可以用正则分支匹配一次性提取信息,避免重复写case_when:

d_target <- d %>%
  pivot_longer(-id, names_to = "var_name", values_to = "value") %>%
  mutate(
    # 正则分支匹配三种变量名模式
    match_res = str_match(var_name, "^(X1_hg)(\\d*)$|^(cuphg_m)0?(\\d+)$|^(cuphg_v)0?(\\d+)$"),
    var_group = coalesce(match_res[,2], match_res[,3], match_res[,5]),
    index = coalesce(
      ifelse(match_res[,2] == "X1_hg" & is.na(match_res[,3]), 1, as.integer(match_res[,3])),
      as.integer(match_res[,4]),
      as.integer(match_res[,6])
    )
  ) %>%
  select(-match_res) %>%
  pivot_wider(names_from = var_group, values_from = value) %>%
  arrange(id, index)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 05:39:51