如何使用dplyr以编程方式结合正则表达式计算变量对的差值并生成新列?
批量创建国家差值列的解决方案
我来帮你搞定这个问题,其实用dplyr结合正则表达式就能轻松实现批量计算每个国家的delta列,下面给你几种不同的思路,你可以根据自己的需求选择:
方法一:手动指定计算(适合国家数量少的场景)
如果只有countrya和countryb两个国家,直接在mutate里分别计算就行,代码简单直观:
library(tibble) library(dplyr) # 原始数据 tib <- tribble( ~id, ~var1_countrya, ~var2_countrya, ~var1_countryb, ~var2_countryb, 1, 1, 2, 1, 2, 2, 5, 3, 1, 3, 3, 6, 3, 1, 3 ) # 计算delta列 tib %>% mutate( delta_countrya = var2_countrya - var1_countrya, delta_countryb = var2_countryb - var1_countryb )
运行后就能得到你想要的结果,每个国家的差值列都准确生成了。
方法二:批量自动处理(适合国家数量多的场景)
如果后续会增加更多国家,手动写每个delta列就太麻烦了,我们可以用正则表达式自动识别所有国家后缀,批量计算:
library(stringr) # 需要用到字符串处理函数 # 从变量名中提取所有唯一的国家后缀 countries <- unique(str_extract(names(tib)[-1], "(?<=var\\d_).+$")) # 批量生成delta列 tib %>% mutate( across( all_of(countries), ~ get(paste0("var2_", .x)) - get(paste0("var1_", .x)), .names = "delta_{.col}" ) )
代码解释:
str_extract(names(tib)[-1], "(?<=var\\d_).+$"):用正则正向断言,提取var1_或var2_后面的国家名称(比如从var1_countrya里取出countrya)across(all_of(countries), ...):遍历每个国家,计算对应的var2_国家名 - var1_国家名.names = "delta_{.col}":自动设置新列的名称为delta_国家名,不用手动命名
方法三:用pivot转换格式实现(tidy数据思路)
另一种更符合tidyverse风格的方法是先把宽格式数据转成长格式,计算差值后再转回宽格式:
tib %>% # 把宽格式转成长格式,拆分变量名为"var1/var2"和"国家名" pivot_longer( cols = -id, names_to = c(".value", "country"), names_pattern = "(var\\d)_(.+)" ) %>% # 计算每个国家的差值 mutate(delta = var2 - var1) %>% # 转回宽格式,设置列名格式 pivot_wider( id_cols = id, names_from = country, values_from = c(var1, var2, delta), names_glue = "{.value}_{country}" )
这种方法的好处是逻辑更清晰,即使变量名规则有小变化,调整正则表达式就能适配。
运行以上任意一种方法,都能得到你想要的最终tibble结果。
内容的提问来源于stack exchange,提问作者Tea Tree
相关产品推荐
相关产品推荐

