如何基于列名规则批量生成新列?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
相关产品推荐
相关产品推荐

