Dplyr rename_with报列名重复错误 自定义函数实际生成唯一列名
报错核心原因
rename_with的逻辑是把选中的所有列名拼成一个字符向量,一次性传入你给的重命名函数,和sapply逐个传入单个列名的运行逻辑完全不同。
你写的renameCol是按单值输入设计的:函数里写死了取str_match_all返回结果的第一个元素[[1]],当一次性传入4个列名时,str_match_all会返回长度为4的匹配列表,你只提取了第一个列名对应的匹配结果,导致4个列全被重命名为Switch_11,自然触发列名重复的报错。sapply运行时每次只传1个列名进函数,[[1]]取到的永远是当前传入列名的匹配结果,所以不会出问题。
修复方案
二选一即可:
- 方案1:把函数改成支持向量输入,适配
rename_with的传参逻辑,这是最稳妥的写法
library(tidyverse) renameCol = function(colname) { # 改用支持向量输入的str_match,不用固定取列表第一个元素 match_res = str_match(colname, "HealthcareProvider(?:TaxonomyCode|PrimaryTaxonomySwitch)_([0-9]+)") coltype = str_remove(match_res[,2], "^(Taxonomy|PrimaryTaxonomy)") col_num = match_res[,3] return(paste0(coltype, "_", col_num)) } tb = tibble( HealthcareProviderPrimaryTaxonomySwitch_11 = 1, HealthcareProviderTaxonomyCode_3 = 2, HealthcareProviderPrimaryTaxonomySwitch_9 = 3, HealthcareProviderTaxonomyCode_13 = 4 ) # 测试运行 tb %>% rename_with(renameCol)
运行后正常输出:
# A tibble: 1 × 4 Switch_11 Code_3 Switch_9 Code_13 <dbl> <dbl> <dbl> <dbl> 1 1 2 3 4
- 方案2:不想修改原有
renameCol函数的话,在rename_with里套一层逐元素处理的逻辑,模拟sapply的传参效果
# 写法1:套sapply逐列处理 tb %>% rename_with(~sapply(.x, renameCol, USE.NAMES = FALSE)) # 写法2:用Vectorize把原函数转成支持向量输入的版本 tb %>% rename_with(Vectorize(renameCol))
两种写法都能得到和手动赋值colnames完全一致的结果。
内容的提问来源于stack exchange,提问作者abalter
相关产品推荐
相关产品推荐

