在 Dataframe 上使用invoke_map()或exec()

tpgth1q7  于 2024-01-03  发布在  其他
关注(0)|答案(2)|浏览(100)

我有一个嵌套框架,其中不同的行需要不同的求值来计算结果。这些求值中的每一个都在一个函数中实现,并且要使用的相应函数在嵌套框架中的一列中指定。下面是一个最小的例子:

f1 = function(a,...){return(2*a)}
f2 = function(a,b,...){return(a+b)}

df = data.frame(a=1:4,b=5:8,f=c('f1','f2','f2','f1'))

#Expected result:
  a b  f result
1 1 5 f1      2
2 2 6 f2      8
3 3 7 f2     10
4 4 8 f1      8

字符串
使用pmap,我可以将一个函数应用到一个嵌套框的每一行,我也读到了关于exec()替换invoke_map()的文章,但是我试图合并两者都不起作用,因为exec()似乎只适用于列表:

df$result = purrr::pmap(df,df$f)
df$result = purrr::pmap(df$f,exec,df)
...


有没有一种比过滤每个函数的嵌套框架更优雅的方法,在每个过滤后的嵌套框架上使用pmap,然后将所有内容绑定在一起?
在此先谢谢您!
编辑:我应该提到的是,我的框架有很多列,并且函数不需要相同的参数(例如,有些函数可能会跳过“a "”,但需要" b "")。因此,我需要一个不需要显式传递参数的方法。

velaa5lx

velaa5lx1#

可以使用exec()和pmap()来实现

f1 <- function(a, ...) return(2 * a)
f2 <- function(a, b, ...) return(a + b)

df <- data.frame(a= 1:4, b = 5:8, f = c('f1', 'f2', 'f2', 'f1'))

require(purrr)
require(dplyr)

df |> mutate(result = pmap(list(f, a, b), exec))
#>   a b  f result
#> 1 1 5 f1      2
#> 2 2 6 f2      8
#> 3 3 7 f2     10
#> 4 4 8 f1      8

字符串
创建于2022-05-27由reprex package(v2.0.1)
PS.你可能会得到一个错误,因为你正在向exec()传递命名参数。当你pmap(list(f = "f1", a = 1, b = 1), exec)时,所有命名参数都传递给exec(.fn, ...)中的...,因为没有一个列表元素被命名为.fn
在上面的例子中,传递的列表元素不带名称,因此第一个参数(通过exec())被假定为.fn
因此,您可以将您建议的方法与base::unname()结合使用:

df |> relocate(f) |> unname() |> pmap(exec)
# [[1]]
# [1] 2
#
# [[2]]
# [1] 8
# 
# [[3]]
# [1] 10
#
# [[4]]
# [1] 8


如果没有unname(),你会得到错误:

df |> relocate(f) |> pmap(exec)
# Error in .f(f = .l[[1L]][[i]], a = .l[[2L]][[i]], b = .l[[3L]][[i]], ...):
#   argument ".fn" is missing, with no default


或者,您可以将df$f重命名为df$.fn并传递整个data.frame:

df |> rename(.fn = "f") |> pmap(exec)
# [[1]]
# [1] 2
#
# [[2]]
# [1] 8
# 
# [[3]]
# [1] 10
#
# [[4]]
# [1] 8
pwuypxnk

pwuypxnk2#

对行使用lapply(),对行使用do.call()

df$result = lapply(1:nrow(df), \(i) {
  do.call(df[i,"f"],as.list(subset(df[i,],select=-f)))
})

字符串
输出量:

a     b f     result
  <int> <int> <chr>  <dbl>
1     1     5 f1         2
2     2     6 f2         8
3     3     7 f2        10
4     4     8 f1         8

相关问题