Используйте столбцы фрейма данных в качестве аргументов для функции с помощью pmap

Я пытаюсь вычислить функцию, аргументы которой являются именами столбца во фрейме данных. Мне нужно перебрать каждую строку и вычислить функцию. Кажется, что pmap - изящный способ сделать это, но я вынужден указать нотацию ..1, ..2, чтобы указать позиции столбцов во фрейме данных. Я думаю, что это не очень воспроизводимый способ выполнения этого.

Хотя он просто знает имена столбцов, когда я использую анонимную функцию вместо именованной.

library(purrr)
#> Warning: package 'purrr' was built under R version 3.6.3
toy_df <- data.frame(a = 1:10, b = 2:11, c = 3:12) 
toy_function <- function(a, b, c) {
  data.frame(result = a^2 + b^3 + log(a)*c + sin(a)*b)
}

## this fails  
toy_fail <- purrr::pmap(toy_df, ~ toy_function())
#> Error in data.frame(result = a^2 + b^3 + log(a) * c + sin(a) * b): argument "a" is missing, with no default

## this works  
toy_pass <- purrr::pmap(toy_df, ~ toy_function(..1, ..2, ..3))


## this works and I didn't need to specify the positions  
toy_also_pass <- purrr::pmap(toy_df, function(a, b, c){
  data.frame(result = a^2 + b^3 + log(a)*c + sin(a)*b)
})

Создано 28 июля 2020 г. пакетом REPEX (v0.3.0)


person Dilsher Singh Dhillon    schedule 28.07.2020    source источник


Ответы (2)


В базе R:

do.call(rbind, do.call(Map, c(list(f = toy_function), toy_df)))
#        result
# 1    10.68294
# 2    36.50048
# 3    79.05754
# 4   145.53375
# 5   246.51252
# 6   391.37817
# 7   583.76908
# 8   822.69864
# 9  1109.29066
# 10 1452.64679

В tidyverse эквивалент будет

purrr::invoke(purrr::pmap_dfr, list(.f = toy_function, .l = toy_df))

но это позволяет гораздо проще

purrr::pmap_dfr(toy_df, toy_function)
person r2evans    schedule 28.07.2020

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

purrr::pmap(toy_df, toy_function)

Или другой вариант

purrr::pmap(toy_df, ~  do.call(toy_function, as.list(c(...))))

Или используя rowwise

library(dplyr)
toy_df %>%
     rowwise %>%
     transmute(result = toy_function(a, b, c))          
person akrun    schedule 28.07.2020
comment
О, черт возьми, это интересно - спасибо! Нужна ли нам тильда только тогда, когда мы указываем .x, .y в map2? Есть ли необходимость в этом в pmap? - person Dilsher Singh Dhillon; 29.07.2020
comment
есть необходимость? это много для удобства, когда имена и / или должности не совпадают идеально. В таком случае в традиционном R можно было бы написать function(...) { ... }, многословно написанную анонимную функцию. rlang допускает более краткое описание с использованием формата тильды (хотя здесь он работает только потому, что pmap знает о тильде-функциях rlang). - person r2evans; 29.07.2020