将具有多变量函数列表变量的数据框应用于具有函数参数的数据框
Apply data frame with list-variable of multivariable functions to a data frame with function arguments
这个数据框包含我称之为 "data":
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))
这是一个数据框,我打算将其用作函数查找之类的东西 table。 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
中的函数重新定义为两个变量的显式函数使事情变得容易得多,那也很好。
期望的输出:
#> # 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 <fn> <fn> 1.00 9.00
#> 2 cat 2.00 4.00 <fn> <fn> 4.00 36.0
#> 3 dog 3.00 6.00 <fn> <fn> 1.73 3.00
#> 4 dog 4.00 8.00 <fn> <fn> 2.00 3.46
(问题由今天早些时候的一个不幸的自我删除问题引起。)
我们可以使用 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 中的 post.
相同
"If re-defining the functions in f2 to be explicitly functions of two variables makes things much easier, that's fine too."
是的,我认为这是更自然的情况。否则数据按行存储,并且可能会被重塑。
重新定义函数:
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()
结果相同。
这个数据框包含我称之为 "data":
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))
这是一个数据框,我打算将其用作函数查找之类的东西 table。 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
中的函数重新定义为两个变量的显式函数使事情变得容易得多,那也很好。
期望的输出:
#> # 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 <fn> <fn> 1.00 9.00
#> 2 cat 2.00 4.00 <fn> <fn> 4.00 36.0
#> 3 dog 3.00 6.00 <fn> <fn> 1.73 3.00
#> 4 dog 4.00 8.00 <fn> <fn> 2.00 3.46
(问题由今天早些时候的一个不幸的自我删除问题引起。)
我们可以使用 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 中的 post.
相同"If re-defining the functions in f2 to be explicitly functions of two variables makes things much easier, that's fine too."
是的,我认为这是更自然的情况。否则数据按行存储,并且可能会被重塑。
重新定义函数:
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()
结果相同。