如何在R(dplyr 0.7.4)中批量按指定长度截断数据框列?
批量截断数据框指定字段至不同长度的解决方案
问题背景
现有如下数据框,需要将first_name截断至3个字符,last_name截断至5个字符:
library(dplyr) id <- c(1111, 2222, 3333, 4444, 5555) first_name <- c("Jonathan", "Sally", "Courtney", "Stephen", "Matthew") last_name <- c("Johnson", "Montgomery", "Cunningham", "Stephenson", "Matthews") Height <- c(200, 160, 170, 180, 190) df <- data.frame(id, first_name, last_name, Height, stringsAsFactors = FALSE)
编写了单个字段截断函数,单独调用时可正常运行:
truncate_fields <- function(df, field, n) { df_tr <- mutate(df, {{field}} := str_trunc({{field}}, n, ellipsis = "")) return(df_tr) }
但尝试通过循环批量处理时:
fields <- c("first_name", "last_name") lengths <- c(3, 5) for(i in 1:length(fields)) { df <- truncate_fields(df, noquote(fields)[i], lengths[i]) }
出现报错:
Error in `splice()`: ! The LHS of `:=` must be a string or a symbol
使用lapply/mapply也未成功,当前使用dplyr 0.7.4版本,需解决批量处理问题。
解决方法
方法1:修改原函数适配字符串输入
dplyr 0.7.4不支持新版的{{}}语法处理字符串输入,需要将字符串字段名转换为符号后注入表达式:
library(stringr) # 需加载stringr包以使用str_trunc truncate_fields <- function(df, field, n) { field_sym <- sym(field) # 将字符串转为符号 df_tr <- mutate(df, !!field_sym := str_trunc(!!field_sym, n, ellipsis = "")) return(df_tr) }
修改后即可正常循环调用:
fields <- c("first_name", "last_name") lengths <- c(3, 5) for(i in seq_along(fields)) { df <- truncate_fields(df, fields[i], lengths[i]) }
方法2:使用mutate_at+purrr::map2批量处理(更简洁)
无需单独编写函数,直接结合mutate_at和map2实现字段与截断长度的配对处理:
library(stringr) library(purrr) df <- df %>% mutate_at(vars(fields), ~map2(., lengths, function(x, n) str_trunc(x, n, ellipsis = "")))
报错原因
原函数中的{{field}}(拥抱语法)是dplyr 1.0.0及以上版本引入的特性,用于直接处理符号类型的字段名。但在0.7.4版本中,传入字符串时{{field}}无法正确转换为合法的符号,导致:=左侧不符合语法要求,从而触发报错。通过sym()转换字符串为符号,再用!!(解引用)注入表达式,即可适配旧版本的tidyeval规则。
内容的提问来源于stack exchange,提问作者Annabanana
相关产品推荐
相关产品推荐

