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

如何在R中基于'total_'前缀列高效透视数据框?

解决方案

我们可以通过列分组标记+正则匹配的方式,用tidyr::pivot_longer一次性完成多组数据的透视,避免多次调用的繁琐。具体步骤如下:

1. 加载必要包

首先确保加载dplyr、tidyr和stringr包:

library(dplyr)
library(tidyr)
library(stringr)

2. 自动生成列分组标识

先给每个非index的列分配所属的分组(对应收入、年龄、语言三类),核心是利用cumsum对total_开头的列进行累积计数,以此区分不同组:

# 提取所有total_开头的列对应的类别(去掉total_前缀)
group_categories <- str_remove(names(df)[grepl("^total_", names(df))], "^total_")
names(group_categories) <- paste0("group_", seq_along(group_categories))

3. 一次性透视多组数据

先给列名添加分组前缀,再通过两次透视(长转宽+宽转长)完成结构重塑,同时自动填充每组的总计值:

result <- df %>%
  # 给非index列添加分组前缀(如group_1_total_income)
  rename_with(function(col) {
    group_idx <- cumsum(grepl("^total_", names(df)))[which(names(df) == col)]
    paste0("group_", group_idx, "_", col)
  }, -index) %>%
  # 转成长格式,拆分分组和原列名
  pivot_longer(
    cols = -index,
    names_to = c("group", "variable"),
    names_sep = "_",
    extra = "merge"  # 处理列名含下划线的情况(如ten_twenty_k)
  ) %>%
  # 把分组映射为对应的类别(收入/年龄/语言)
  mutate(category = group_categories[group]) %>%
  # 区分总计列和分项列,去掉总计列的total_前缀
  mutate(
    is_total = str_starts(variable, "total_"),
    variable = str_remove(variable, "^total_")
  ) %>%
  # 转成宽格式,让总计值和分项值同属一行
  pivot_wider(
    id_cols = c(index, category, variable),
    names_from = is_total,
    values_from = value,
    names_glue = "{ifelse(is_total, 'total_value', 'item_value')}"
  ) %>%
  # 为每组的所有行填充总计值
  group_by(index, category) %>%
  fill(total_value, .direction = "downup") %>%
  ungroup() %>%
  # 过滤掉无分项值的行(原总计行)
  filter(!is.na(item_value)) %>%
  # 重命名列并调整顺序
  rename(item = variable) %>%
  select(index, category, item, item_value, total_value)

处理后的result结构示例(前5行):

# A tibble: 9 × 5
  index category item               item_value total_value
  <int> <chr>    <chr>                    <dbl>       <dbl>
1     1 income   ten_twenty_k                90         100
2     1 income   twenty_one_thirty_k         10         100
3     1 age      age_15_lower                10        1000
4     1 age      age_16_30                  900        1000
5     1 age      age_31_50                   90        1000

4. 拆分数据框并去重

按category拆分数据框,并用distinct()去除重复行:

# 按类别拆分数据框
split_dfs <- result %>%
  group_split(category, .keep = TRUE)

# 给拆分后的列表命名
names(split_dfs) <- unique(result$category)

# 对每个数据框去重
split_dfs <- lapply(split_dfs, function(df) {
  df %>% distinct()
})

拆分后可通过split_dfs$income、split_dfs$age、split_dfs$language分别访问对应的数据框。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 07:58:11