Использование анонимной функции в mutate - PullRequest
0 голосов
/ 20 декабря 2018

Я хочу использовать строки символов из одного столбца кадра данных в качестве строки поиска в 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

Вот код, который работает, используя apply:

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

Можно ли это сделать без apply?

1 Ответ

0 голосов
/ 20 декабря 2018

Очевидно, что вам нужна целая куча скобок.См. https://stackoverflow.com/a/36906989/3277050

В вашей ситуации это выглядит следующим образом:

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

Так что, если вы заключите определение всей функции в скобки, вы сможете обработать ее как обычную функцию иаргументы этому.

Новый ответ

На самом деле это совсем не тот способ использовать мутирование.Сначала я сосредоточился на части анонимной функции, не глядя на то, что вы на самом деле делаете.Что вам нужно, это векторизованная версия 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))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...