Функция обертывания purrr :: pmap с использованием имен столбцов

Я пытаюсь написать простую функцию, оборачивающуюся вокруг функции purrr :: pmap_dbl ().

У меня есть следующие данные:

df <- data.frame(
          col1 = 1:5, 
          col2 = 2:6, 
          col3 = 3:7
)

И следующая функция:

addfn <- function(x, y){
   x^2 + y
}

Тогда я хотел бы написать такую ​​функцию, как:

testfn <- function(data, a, b){
    purrr::pmap_dbl(data, function(a, b, ...) addfn(a, b))
}

К сожалению, testfn(df, col1, col2) в этом случае выдает ошибку. Я хотел бы получить тот же результат, что и результат, полученный с помощью:

purrr::pmap_dbl(df, function(col1, col2, ...) addfn(col1, col2))

Как это сделать?


person mharinga    schedule 02.02.2018    source источник


Ответы (3)


1) testfn Во-первых, обратите внимание, что при использовании testfn из вопроса, что это уже работает:

testfn(unname(df[c("col1", "col3")]))
## [1]  4  8 14 22 32

2) testfn2, и мы можем изменить это на:

testfn2 <- function(data, ...) {
  data %>% select(...) %>% unname %>% purrr::pmap_dbl(addfn)
}

testfn2(df, col1, col3)
## [1]  4  8 14 22 32

testfn2(df, "col1", "col3")
## [1]  4  8 14 22 32

3) base R. Конечно, как уже указывалось, для этого нам действительно не нужно мурлыкать. Это работает в базе R, потому что addfn векторизован:

with(df, addfn(col1, col3))
## [1]  4  8 14 22 32

или если addfn не были векторизованы, то:

with(df, mapply(addfn, col1, col3))
## [1]  4  8 14 22 32

и мы могли бы написать эту функцию, используя стандартную оценку:

testfn3 <- function(data, a, b) mapply(addfn, df[[a]], df[[b]])

testfn3(df, "col1", "col3")
## [1]  4  8 14 22 32

или используя нестандартную оценку:

testfn4 <- function(data, ...) eval.parent(substitute(
  with(data, mapply(addfn, ...))
))

testfn4(df, col1, col3)
## [1]  4  8 14 22 32
person G. Grothendieck    schedule 02.02.2018

Вы можете выбрать свой df, прежде чем использовать его на карте:

library(rlang)
library(dplyr)
library(purrr)
testfn <- function(data, x, y){
  data <- select(data, !!enquo(x), !!enquo(y))
  pmap_dbl(data, ~ addfn(.x, .y))
}

testfn(df, col1, col3) 
person Colin FAY    schedule 02.02.2018
comment
Это хорошая работа. Однако я хотел бы знать, можно ли напрямую вызывать имена столбцов. - person mharinga; 02.02.2018
comment
Одна из основных целей использования tidyverse (например, dplyr и purrr) - иметь код, которому легко следовать. Я не вижу, как @ColinFAY улучшается в этом отношении по сравнению с пакетами base R, см. Комментарий akrun ниже. - person nadizan; 02.02.2018

Или вы можете использовать apply функции.

addfn <- function(x){
  apply(x,1,function(y) y[1]^2 + y[2])
}

addfn(df[,1:2])
[1]  3  7 13 21 31

addfn(df[,2:3])
[1]  7 13 21 31 43
person nadizan    schedule 02.02.2018
comment
Если вы используете base R методы, тогда x[,1]^2 + x[,2] будет более компактным и быстрым. - person akrun; 02.02.2018
comment
Конечно, но похоже, что автору темы нужна была именно функция. Но я мог неправильно понять. - person nadizan; 02.02.2018