在mutate中使用匿名函数

时间:2018-12-20 14:09:59

标签: r

我想在逐行的基础上sub搜索数据帧另一列中的字符串时使用数据帧中一列的字符串作为搜索字符串。我想使用dplyr::mutate来做到这一点。我已经找到了一种使用匿名函数和apply来完成此操作的方法,但是我觉得apply不必要,我在实现{{1 }}。 (是的,我知道mutate可以给我最终结果,而无需使用mutate;我只想了解如何使用tools::file_path_sans_ext。)

以下是我认为应该起作用但不起作用的代码:

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 的代码:

apply

可以在没有files.split.df <- files.paths.df %>% mutate(no.ext = apply(., 1, function(x) { sub(paste0(".", x["extension"], "$"), "", x["file"]) })) 的情况下完成此操作吗?

1 个答案:

答案 0 :(得分:2)

显然,您需要一大堆括号。参见https://stackoverflow.com/a/36906989/3277050

根据您的情况,它看起来像:

files.split.df <- files.paths.df %>% 
  mutate(
    no.ext = (function(x) {sub(paste0(".", x["extension"], "$"), "", x["file"])})(.)
  )

因此,如果将整个函数定义包装在方括号中,则可以将其视为常规函数并为其提供参数。

新答案

确实,这根本不是使用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, "$"), ""))

编辑以回答评论

要在没有现有矢量化函数的情况下使用用户定义的函数,可以使用Vectorize,如下所示:

string_fun <- Vectorize(function(x, y) {sub(paste0(".", x, "$"), "", y)})
files.split.df <- files.paths.df %>% 
  mutate(
    no.ext = string_fun(extension, file))

或者如果您真的不想命名该函数,我不建议这样做,因为它很难阅读:

files.split.df <- files.paths.df %>% 
  mutate(
    no.ext = (Vectorize(function(x, y) {sub(paste0(".", x, "$"), "", y)}))(extension, file))