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

如何基于列名规则批量生成新列?tidyverse大数据集免pivot_longer方案

批量计算对应列比值的高性能tidyverse实现方案

我有一个列名遵循统一规则的数据集,需要计算多组对应两列的比值生成新列。我希望使用tidyverse方案实现,但由于数据集行数超过百万,不想使用pivot_longer以免产生过大的性能开销。

示例数据集

library(dplyr)

df <- tibble(
  jan_mean = runif(10),
  feb_mean = runif(10),
  mar_mean = runif(10),
  jan_sd = runif(10),
  feb_sd = runif(10),
  mar_sd = runif(10),
)

手动实现方案

df2 <- df %>% 
  mutate(jan_cv= jan_mean/jan_sd,
         feb_cv= feb_mean/feb_sd,
         mar_cv= mar_mean/mar_sd
         )

以上仅为简单示例,实际场景中需要对所有月度值执行同类操作。

三种实现方案性能对比

为了验证不同方案在大数据量下的性能表现,对三种实现方法做了测试:方法1为手动逐列计算,方法2为动态匹配列名的简洁方案,方法3为使用pivot系列函数做长宽表转换的方案,测试代码如下:

tic("Method 1: manual option")
df2 <- df %>% 
  mutate(jan_cv= jan_mean/jan_sd,
         feb_cv= feb_mean/feb_sd,
         mar_cv= mar_mean/mar_sd
  )
toc()

tic("Method 2: Short option")
df2 <- df %>%
  mutate(across(ends_with('_mean'), ~ . /
                  get(str_replace(cur_column(), "mean$", "sd")), .names = "{.col}_cv")) %>%
  rename_at(vars(ends_with('cv')), ~ str_remove(., "\\_mean"))
toc()

tic("Method 3: pivot wider option")
df2 <- df %>% 
  mutate(id = row_number()) %>% 
  pivot_longer(-id, names_to = c("month", ".value"), names_sep = "_") %>% 
  mutate(cv = mean / sd) %>% 
  pivot_wider(names_from = "month", values_from = c(mean, sd, cv), names_glue = "{month}_{.value}") %>% 
  select(-id)
toc()

测试结果如下:

Method 1: manual option: 0.05 sec elapsed
Method 2: Short option: 0.01 sec elapsed
Method 3: pivot wider option: 0.19 sec elapsed

测试结果显示,方法2的执行速度甚至比手动逐列计算还要快,性能远优于长宽表转换的方案,非常适合处理百万行级别的大数据集。

内容的提问来源于stack exchange,提问作者G. Rocher

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 22:54:05