我想使用数据帧的一列中的字符串作为搜索字符串,逐行搜索sub数据帧的另一列中的字符串。我想使用 来做到这一点dplyr::mutate。我已经找到了一种使用匿名函数 和 来做到这一点的方法apply,但我觉得apply没有必要,而且我的实现方式一定是出了问题mutate。(是的,我知道这tools::file_path_sans_ext可以给我最终结果而不需要使用 mutate ;我只是想了解如何使用mutate。)
这是我认为应该有效但无效的代码:
files.vec <- dir(
dir.target,
full.names = T,
recursive = T,
include.dirs = F,
no.. = T
)
library(tools)
files.paths.df <- as.data.frame(
cbind(
path = files.vec,
directory = dirname(files.vec),
file = basename(files.vec),
extension = file_ext(files.vec)
)
)
library(tidyr)
library(dplyr)
files.split.df <- files.paths.df %>%
mutate(
no.ext = function(x) {
sub(paste0(".", x["extension"], "$"), "", x["file"])
}
)
| Error in mutate_impl(.data, dots) :
| Column `no.ext` is of unsupported type function
Run Code Online (Sandbox Code Playgroud)
这是有效的代码,使用apply:
files.split.df <- files.paths.df %>%
mutate(no.ext = apply(., 1, function(x) {
sub(paste0(".", x["extension"], "$"), "", x["file"])
}))
Run Code Online (Sandbox Code Playgroud)
没有 可以做到这一点apply吗?
显然你需要的是一大堆括号。请参阅/sf/answers/2583489261/
在你的情况下,它看起来像:
files.split.df <- files.paths.df %>%
mutate(
no.ext = (function(x) {sub(paste0(".", x["extension"], "$"), "", x["file"])})(.)
)
Run Code Online (Sandbox Code Playgroud)
因此,如果将整个函数定义放在括号中,您就可以将其视为常规函数并为其提供参数。
实际上,这根本不是使用 mutate 的正确方法。我首先专注于匿名函数部分,而没有考虑您实际在做什么。您需要的是 sub 的矢量化版本。str_replace所以我从包装中使用stringr。然后你可以只按名称引用列,因为这就是 dplyr 的优点:
library(tidyr)
library(dplyr)
library(stringr)
files.split.df <- files.paths.df %>%
mutate(
no.ext = str_replace(file, paste0(".", extension, "$"), ""))
Run Code Online (Sandbox Code Playgroud)
要在没有现有向量化函数的情况下使用用户定义的函数,您可以Vectorize像这样使用:
string_fun <- Vectorize(function(x, y) {sub(paste0(".", x, "$"), "", y)})
files.split.df <- files.paths.df %>%
mutate(
no.ext = string_fun(extension, file))
Run Code Online (Sandbox Code Playgroud)
或者,如果您真的不想命名该函数,我不建议这样做,因为它更难阅读:
files.split.df <- files.paths.df %>%
mutate(
no.ext = (Vectorize(function(x, y) {sub(paste0(".", x, "$"), "", y)}))(extension, file))
Run Code Online (Sandbox Code Playgroud)