自定义R函数调用dplyr mutate时生成新列而非修改原列的问题
数据清洗函数问题分析与解决
问题重现
创建的数据框:
id<-c("id1","id2","id3","id4","id5","id6") out<-c("50","60","60 4d", "60.4","5823",NA) cov<-c("Male","male","mále","Fe male","female","fema") dat<-data.frame(id,out,cov)
自定义清洗函数:
conv_number<-function(data,variable){ data<- data |> dplyr::mutate(variable = gsub(pattern = ",", replacement = ".", variable)) x<- data |> dplyr::mutate(variable = as.numeric(gsub("[^0-9.-]", "", variable))) return (x) } clean_string<-function(data,variable){ data |> dplyr::mutate(variable = tolower(variable)) x<- data |> dplyr::mutate(variable = gsub("[^a-z]", "", variable)) return (x) }
调用后出现的问题:
- 函数未修改目标列,反而生成名为
variable的新列 clean_string函数无法正确将带重音的字符(如mále)转为小写
问题原因
- 列名引用错误:在
dplyr::mutate中直接写variable = ...时,会把variable当作新列名,而非引用传入的目标列。需使用tidy评估语法{{ variable }}捕获传入的列参数,实现动态修改原列。 - 管道结果未传递:
clean_string函数中第一行的data |> mutate(...)未赋值给变量,后续x仍基于原始data处理,导致tolower操作完全无效。 - 小写转换不支持Unicode:基础
tolower()仅能处理ASCII字符,无法转换带重音的Unicode字符(如á),需使用支持多语言的转换函数。
修正后的代码
修正conv_number函数
使用{{ variable }}引用目标列,保留原列名完成修改:
conv_number<-function(data, variable){ data |> dplyr::mutate({{ variable }} := gsub(pattern = ",", replacement = ".", {{ variable }}), {{ variable }} := as.numeric(gsub("[^0-9.-]", "", {{ variable }}))) }
修正clean_string函数
使用stringr::str_to_lower处理Unicode字符,正确传递管道结果并修改原列:
library(stringr) clean_string<-function(data, variable){ data |> dplyr::mutate({{ variable }} := str_to_lower({{ variable }}), {{ variable }} := gsub("[^a-záéíóú]", "", {{ variable }})) }
测试调用
# 处理数值列 prueba_1 <- conv_number(dat, out) # 处理字符列 prueba_1 <- clean_string(prueba_1, cov) # 查看结果 print(prueba_1) # id out cov # 1 id1 50.0 male # 2 id2 60.0 male # 3 id3 60.4 male # 4 id4 60.4 female # 5 id5 5823. female # 6 id6 NA fema
内容的提问来源于stack exchange,提问作者Francisco
相关产品推荐
相关产品推荐

