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

如何基于变量共同前缀将R语言宽表转为长表?

解决R语言宽表转长表(带前缀分组)的问题

原始宽格式数据

# 示例数据,还有更多类似x_、y_开头的变量
df <- data.frame(id = c(1,2,3), x_num = c(9,8,7), y_num = c(6,5,4), 
                 x_text_long = c("a","b","c"), y_text_long = c("d","e","f"), 
                 z = c(T,F,F))

期望的长格式数据

# 目标长表
target <- data.frame(id = c(1,1,2,2,3,3), type = c("x","y","x","y","x","y"), 
                     num = c(9,6,8,5,7,4), text_long = c("a","d","b","e","c","f"),
                     z = c(T,T,F,F,F,F))

需求说明

将宽表转换为长表,核心要求:

  • 对以x_和y_为前缀的变量分组,生成type列标记前缀(x或y)
  • 前缀后的部分作为新的列名(比如x_num对应type=x,值归入num列)
  • 保留id、z等不参与分组的变量的对应值(每个type分组下重复这些值)

尝试过的无效方法

方法1:单次处理一组变量,效率低

# 只能逐个处理(x,y)变量对,效率不高
df[c("x_num","y_num")] %>% 
  pivot_longer(
    cols = `x_num`:`y_num`, 
    names_to = "type",
    values_to = "values"
  ) %>% 
  mutate(type=substring(type,1,1))

方法2:reshape函数输出不符合预期

# 输出结果不符合需求
reshape(df,
        direction = "long",
        varying = list(names(df)[2:5]),
        v.names = "values",
        idvar = c("id"),
        timevar = "type")

可行解决方案

方案1:基于tidyverse的pivot_longer(推荐)

使用tidyr包的pivot_longer函数,通过拆分变量名一次性完成转换,同时保留非分组变量:

library(tidyr)
library(dplyr)

result <- df %>%
  pivot_longer(
    cols = starts_with(c("x_", "y_")),  # 选择所有x_、y_开头的变量
    names_to = c("type", ".value"),     # 拆分变量名:前缀存入type,剩余部分作为新列名
    names_sep = "_"                     # 按下划线拆分变量名
  )

# 查看结果
result

运行后得到的结果与目标target完全一致:

# A tibble: 6 × 4
     id z     type  num text_long
  <dbl> <lgl> <chr> <dbl> <chr>    
1     1 TRUE  x         9 a        
2     1 TRUE  y         6 d        
3     2 FALSE x         8 b        
4     2 FALSE y         5 e        
5     3 FALSE x         7 c        
6     3 FALSE y         4 f        

核心参数说明

  • cols = starts_with(c("x_", "y_")):精准选择需要转换的变量,避免手动输入列名
  • names_to = c("type", ".value"):type存储拆分出的前缀(x/y),.value表示用拆分后的剩余部分作为新列名,自动匹配对应值
  • names_sep = "_":指定变量名的拆分分隔符为下划线

方案2:基于base R的reshape函数

如果不想依赖tidyverse,可通过正确配置reshape参数实现:

result_base <- reshape(df,
                       direction = "long",
                       varying = list(c("x_num", "y_num"), c("x_text_long", "y_text_long")),
                       v.names = c("num", "text_long"),
                       idvar = c("id", "z"),
                       timevar = "type",
                       times = c("x", "y"))

# 调整列顺序与目标一致
result_base <- result_base[, c("id", "type", "num", "text_long", "z")]
rownames(result_base) <- NULL  # 重置行名

result_base

运行后输出:

id type num text_long     z
1  1    x   9         a  TRUE
2  2    x   8         b FALSE
3  3    x   7         c FALSE
4  1    y   6         d  TRUE
5  2    y   5         e FALSE
6  3    y   4         f FALSE

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 02:36:05