编写tidyverse函数:移除字符列非数字内容转数值遇问题
问题描述
需要处理tibble中的字符列,移除所有非数字字符并转换为数值类型。输入数据如下:
species <- c('Carabus dufouri', 'Opuntia ficus-indica', 'Lycaena phlaeas') number <- ('3 adults', '4 and a half stands', '8 caterpillars') data <- tibble (species, number) data # A tibble: 3 x 2 species number <chr> <chr> 1 Carabus dufouri 3 adults 2 Opuntia ficus-indica 4 and a half stands 3 Lycaena phlaeas 8 caterpillars
期望输出:
number_f <- c(3, 4, 8) data_f <- tibble (species, number_f) data_f species number_f <chr> <dbl> 1 Carabus dufouri 3 2 Opuntia ficus-indica 4 3 Lycaena phlaeas 8
尝试封装函数后,mutate未生效:
num_fix <- function(data, spalte) { satz <- as.double(gsub("([0-9]+).*$", "\\1", data[[spalte]])) data %>% mutate(spalte = satz) }
问题原因
函数中mutate(spalte = satz)会创建一个名为spalte的字面量列,而非引用传入的参数(比如number)作为列名。这是tidyverse非标准求值的特性,直接使用变量名会被解析为列名字符串,而非动态引用参数值。
解决方法
方法1:用{{}}和:=动态绑定列名(推荐)
这是tidyverse官方推荐的处理动态列名的方式,{{}}用于引用函数参数,:=用于动态指定列名:
替换原列版本
num_fix <- function(data, spalte) { satz <- as.double(gsub("([0-9]+).*$", "\\1", data[[spalte]])) data %>% mutate({{spalte}} := satz) } # 使用示例 data_fixed <- num_fix(data, number)
生成新列版本(后缀加_f)
如果想保留原列,生成带后缀的新列:
num_fix <- function(data, spalte) { # 获取传入的列名字符串 col_name <- deparse(substitute(spalte)) new_col <- paste0(col_name, "_f") satz <- as.double(gsub("([0-9]+).*$", "\\1", data[[col_name]])) data %>% mutate({{new_col}} := satz) } # 使用示例 data_fixed <- num_fix(data, number)
方法2:支持字符串形式的列名输入
如果调用函数时传入的是字符串格式的列名(比如"number"),可以用!!(bang-bang)运算符解析:
num_fix <- function(data, spalte) { satz <- as.double(gsub("([0-9]+).*$", "\\1", data[[spalte]])) data %>% mutate(!!spalte := satz) } # 使用示例 data_fixed <- num_fix(data, "number")
运行上述修正后的函数,即可得到符合预期的数值列。
内容的提问来源于stack exchange,提问作者Tuck
相关产品推荐
相关产品推荐

