将具有多变量函数的列表变量的数据帧应用于具有函数参数的数据帧

时间:2018-03-13 21:23:15

标签: r purrr

此数据框包含我称之为"数据":

INT

这是一个我打算用作函数查找表的数据框。 library(tidyverse) df_d <- data_frame(key = c("cat", "cat", "dog", "dog"), value_1 = c(1,2,3,4), value_2 = c(2,4,6,8)) 是单变量函数,f是多变量函数:

f2

我可以轻松创建数据框,以便任何df_f <- data_frame(key = c("cat", "dog"), f = c(function(x) x^2, function(x) sqrt(x)), f2 = c(function(x) (x[1]+x[2])^2, function(x) sqrt(x[1]+x[2]))) 行获取cat个函数,任何cat行获取dog函数:

dog

我能够弄清楚如何将每个df_both <- left_join(df_d, df_f) 函数应用到f列以获取:

value_1

我的问题是:如何创建列df_both %>% mutate(result = invoke_map_dbl(f, value_1)) #> # A tibble: 4 x 6 #> key value_1 value_2 f f2 result #> <chr> <dbl> <dbl> <list> <list> <dbl> #> 1 cat 1.00 2.00 <fn> <fn> 1.00 #> 2 cat 2.00 4.00 <fn> <fn> 4.00 #> 3 dog 3.00 6.00 <fn> <fn> 1.73 #> 4 dog 4.00 8.00 <fn> <fn> 2.00 ,其中result2中的每个函数都用作其输入f2。如果将c(value_1, value_2)中的函数重新定义为两个变量的显式函数会使事情变得更容易,那也很好。

期望的输出:

f2

(问题是由于今天早些时候一个不幸的自我删除问题所致。)

2 个答案:

答案 0 :(得分:3)

“如果将f2中的函数重新定义为两个变量的显式函数会使事情变得更容易,那也没关系。”

是的,我认为这将是一个更自然的情况。否则,数据以行方式存储,并且可能应该重新整形。

重新定义您的功能:

df_f <- data_frame(key = c("cat", "dog"),
                   f = c(function(x) x^2, function(x) sqrt(x)),
                   f2 = c(function(x, y) (x + y)^2, function(x, y) sqrt(x + y)))
df_both <- left_join(df_d, df_f)

现在您再次使用map_invoke,将.x作为列表传递,但您需要使用transpose将内容列为内容:

mutate(
  df_both,
  result  = invoke_map_dbl(f, value_1),
  result2 = invoke_map_dbl(f2, transpose(list(value_1, value_2)))
)
# A tibble: 4 x 7
  key   value_1 value_2 f      f2     result result2
  <chr>   <dbl>   <dbl> <list> <list>  <dbl>   <dbl>
1 cat        1.      2. <fn>   <fn>     1.00    9.00
2 cat        2.      4. <fn>   <fn>     4.00   36.0 
3 dog        3.      6. <fn>   <fn>     1.73    3.00
4 dog        4.      8. <fn>   <fn>     2.00    3.46

一组三个参数函数将简单地扩展到invoke_map_dbl(f3, transpose(list(value_1, value_2, value_3))

请注意,这种方法不适用于大型数据集,因为您没有使用矢量化。

更具伸缩性的替代方案可能涉及嵌套,您至少在每个组中应用每个函数一次:

df_both %>% 
  group_by(key) %>% 
  nest() %>% 
  mutate(data = map(
    data, 
    ~mutate(., result = first(f)(value_1), result2 = first(f2)(value_1, value_2))
    )) %>% 
  unnest()

这给出了相同的结果。

答案 1 :(得分:2)

我们可以使用pmap

df_both %>% 
   mutate(result = invoke_map_dbl(f, value_1), 
          result2 = pmap_dbl(.[c('value_1', 'value_2', 'f2')],  ~(..3)(c(..1, ..2))))
# A tibble: 4 x 7
#   key   value_1 value_2 f      f2     result result2
#   <chr>   <dbl>   <dbl> <list> <list>  <dbl>   <dbl>
#1 cat      1.00    2.00 <fun>  <fun>    1.00    9.00
#2 cat      2.00    4.00 <fun>  <fun>    4.00   36.0 
#3 dog      3.00    6.00 <fun>  <fun>    1.73    3.00
#4 dog      4.00    8.00 <fun>  <fun>    2.00    3.46

在这里,我们不会改变OP的功能。这与OP的帖子相同。