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

使用R语言dplyr包将指定列对转换为行(宽表转长表)

解决宽格式DataFrame转长格式(按特定列对分组)的问题

嘿,我来帮你搞定这个宽转长的需求!首先先确认下你的示例数据和目标:

示例数据

你提供的原始数据框代码如下:

df <- data.frame(id=c(1,2,3,4,5), 
                 var=c("a","d","g","f","i"),
                 a1=c(3,5,1,2,2), 
                 b1=c(2,4,1,2,3), 
                 a2=c(8,1,2,5,1), 
                 b2=c(1,6,4,7,2), 
                 a3=c(7,7,2,3,1), 
                 b3=c(1,1,4,9,6))

原始表格长这样:

idvara1b1a2b2a3b3
1a328171
2d541671
3g112424
4f225739
5i231216

你的目标是把a1&b1、a2&b2、a3&b3这样的列对转换成独立的行,最终得到包含id、var、a、b的长格式表格。

解决方案1:使用tidyverse的pivot_longer(推荐)

这是最直观且易读的方法,用到tidyr包的pivot_longer函数:

library(tidyr)

# 执行宽转长
df_long <- df %>%
  pivot_longer(
    cols = starts_with(c("a", "b")),  # 选中所有a/b开头的列
    names_pattern = "(.)(\\d)",       # 用正则捕获列名的前缀(a/b)和数字(1/2/3)
    names_to = c(".value", "group")   # .value表示把前缀作为新列名,group存分组编号
  ) %>%
  select(-group)  # 可选:如果不需要分组编号列就删掉它

代码解释:

  • starts_with(c("a", "b")):精准选中所有需要转换的列(a1、b1到a3、b3)
  • names_pattern = "(.)(\\d)":正则表达式把列名拆成两部分,第一部分是a或b,第二部分是数字编号
  • names_to = c(".value", "group"):.value是特殊参数,它会把捕获的前缀作为新的列名(也就是最终的a和b),group用来存储原来的数字编号(比如1、2、3)

解决方案2:使用Base R的reshape函数

如果你不想加载额外的包,Base R的reshape函数也能实现:

df_long_base <- reshape(
  df,
  direction = "long",          # 指定转换方向为长格式
  varying = list(c("a1","a2","a3"), c("b1","b2","b3")),  # 对应a和b的原始列组
  v.names = c("a", "b"),       # 新列的名字
  idvar = c("id", "var"),      # 保持不变的标识列
  timevar = "group"            # 分组变量名
) %>%
  select(id, var, a, b)  # 调整列顺序到你需要的格式

最终结果

两种方法都会得到你想要的长格式表格,前几行如下:

idvarab
1a32
1a81
1a71
2d54
2d16
2d71

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:01:54