R dplyr мутировать несколько столбцов с помощью пользовательской функции для создания нового столбца - PullRequest
0 голосов
/ 05 февраля 2019

Я хотел бы создать новый столбец в data.frame, используя dplyr::mutate, используя пользовательскую функцию, аргумент которой является вектором имен столбцов data.frame, но я получил следующий вывод:

customFun <- function(col.vec) {
  paste0(gsub("\\s", "_", col.vec), collapse = "-")
}

df <- data.frame(A = c("x 1", "x", "x w"), B = c("E", "D", "2 w"), stringsAsFactors = FALSE)

df %>%
   mutate(C = customFun(c(A, B)))
    A   B                 C
1 x 1   E x_1-x-x_w-E-D-2_w
2   x   D x_1-x-x_w-E-D-2_w
3 x w 2 w x_1-x-x_w-E-D-2_w

вместо:

data.table::data.table(df)[, C := customFun(c(A, B)), by = .(A, B)]
     A   B       C
1: x 1   E   x_1-E
2:   x   D     x-D
3: x w 2 w x_w-2_w

Этого можно достичь разными способами, но меня интересует только решение dplyr.Спасибо за вашу помощь.

Ответы [ 3 ]

0 голосов
/ 05 февраля 2019

Просто добавьте rowwise перед mutate, чтобы в paste использовались только значения * и каждой строки , а не векторы всех строк.

library(dplyr)

df %>%
  rowwise() %>%
  mutate(C = customFun(c(A, B)))
#> Source: local data frame [3 x 3]
#> Groups: <by row>
#> 
#> # A tibble: 3 x 3
#>   A     B     C      
#>   <chr> <chr> <chr>  
#> 1 x 1   E     x_1-E  
#> 2 x     D     x-D    
#> 3 x w   2 w   x_w-2_w

Создано в 2019-02-05 пакетом Представить (v0.2.1)

0 голосов
/ 05 февраля 2019

Зачем использовать by=.(..) в вашем data.table решении?Если у вас вообще есть две строки с одинаковыми значениями, они будут объединены в одну.Вам нужно изменить свой customFun.Неправильно, как это:

library(tidyverse)
customFun = function(data) invoke(paste, data.frame(gsub('\\s+', '_', as.matrix(data))), sep='-')

df %>% 
    mutate(c = customFun(.))

    A   B       C
1 x 1   E   x_1-E
2   x   D     x-D
3 x w 2 w x_w-2_w

Вы можете заменить вызов на do.call или даже lift и т. Д.

Ваша функция не выполняет именно то, что вы хотите.Прочитайте комментарий выше

0 голосов
/ 05 февраля 2019

Мы можем использовать map и lift_dl.Сначала мы map над каждым col.vec (обратите внимание, что я использовал список вместо вектора в качестве входных данных, поскольку c выравнивает любые векторные элементы, а список нет) и применяем gsub.Затем вывод списка подается в paste.Поскольку paste занимает ..., мы можем использовать purrr::lift_dl для поднятия его входного домена с ... до list, типа:

library(dplyr)
library(purrr)

customFun <- function(col.vec) {
  map(col.vec, ~gsub("\\s", "_", .x)) %>%
    lift_dl(paste, sep = "-")()
}

df %>%
  mutate(C = customFun(list(A, B)))

или с ... в качестве ввода:

customFun <- function(...) {
  col.vec <- list(...)
  map(col.vec, ~gsub("\\s", "_", .x)) %>%
    lift_dl(paste, sep = "-")()
}

df %>%
  mutate(C = customFun(A, B))

Выход:

    A   B       C
1 x 1   E   x_1-E
2   x   D     x-D
3 x w 2 w x_w-2_w
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...