使用Furrr进行整洁的评估

如何解决使用Furrr进行整洁的评估

我想使用furrr软件包而不是purrr软件包并行运行以下函数。

library(furrr)
library(tidyverse)

input <- list(element1 = tibble::tibble(a = c(1,2),b = c(2,2)),element2 = tibble::tibble(a = c(1,b = c(4,4))
)

multiplier <- function(data,var1,var2){
  purrr::map_df(.x = data,.f = ~ .x %>% 
                  dplyr::mutate(product = {{var1}} * {{var2}})
  )
}

multiplier(input,a,b)

但是,当我将其转换为等效的furrr时,会出现错误。

multiplier_parallel <- function(data,var2){
  furrr::future_map_dfr(.x = data,.f = ~ .x %>% 
                  dplyr::mutate(product = {{var1}} * {{var2}})
  )
}

future::plan(multiprocess)

multiplier_parallel(input,b)
Error in get(name,envir = env,inherits = FALSE) : 
Identified global objects via static code inspection (structure(function (...,.x = ..1,.y = ..2,. = 
..1); .x %>% dplyr::mutate(product = {; {; var1; }; } * {; {; var2; }; }),class = 
c("rlang_lambda_function","function"))). Object 'a' not found 

我认为原因是future包寻找所有必需的变量以导出到工作程序。在这种情况下,它正在寻找列名“ a”作为全局变量,但找不到它,因此出错。

当我只是将变量名插入到调用中时,它可以工作,但是现在该函数不再适用于任何变量名:

multiplier_parallel <- function(data,.f = ~ .x %>% 
                  dplyr::mutate(product = a * b)
  )
}

multiplier_parallel(input,b)

到目前为止,我已经尝试了几种方法,包括为.future_options提供名称,但是似乎都没有用。有什么办法可以使这项工作吗?我的实际功能要复杂得多,但是我假设原理是相同的。如果有人可以帮助,那就太好了!

解决方法

future尝试自动确定您在代码中使用的全局变量。由于评估工作整洁,因此可以识别ab,但找不到。您可以使用future_options(globals = FALSE)禁用此设置。

future::plan(future::multiprocess)

input <- list(element1 = tibble::tibble(a = c(1,2),b = c(2,2)),element2 = tibble::tibble(a = c(1,b = c(4,4))
)

multiplier_parallel <- function(data,var1,var2){
      furrr::future_map_dfr(.x = data,.f = ~ .x %>% 
                                  dplyr::mutate(product = {{var1}} * {{var2}}),.options = furrr::future_options(globals = FALSE)
      )
}

multiplier_parallel(input,a,b)
# A tibble: 4 x 3
      a     b product
  <dbl> <dbl>   <dbl>
1     1     2       2
2     2     2       4
3     1     4       4
4     2     4       8
,

从最底层看,这似乎是globals包的错误,furrr使用它来查找需要导出到worker的全局变量。我已在https://github.com/HenrikBengtsson/globals/issues/65

上游报告了此错误。

该问题与NSE(非标准评估)有关,其中“全局变量”“寻找”以找到全局变量,并且可以仅使用全局变量和基数R复制。使用全局变量0.13.0,我得到以下信息:

library(globals)

fn <- function(expr) {
  expr <- substitute(expr)
  eval(expr,envir = mtcars)
}

fn(cyl)
#>  [1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4

expr <- quote(fn(cyl))

globalsOf(expr)
#> Error in globalsByName(names,envir = envir,mustExist = mustExist): Identified global objects via static code inspection (fn(cyl)). Failed to locate global object in the relevant environments: 'cyl'

错误消息有些不同,但是我可以肯定这是相同的潜在问题。

很好奇的是,对列进行硬编码时没有错误发生,但是我们仍然延迟评估。即可以,但是结果很长,所以我不会显示输出:

library(globals)

fn <- function() {
  expr <- quote(cyl)
  eval(expr,envir = mtcars)
}

fn()

expr <- quote(fn())

globalsOf(expr)
,

啊,在我以前的回答中,我忘记了这是furrr的“常见陷阱”之一。前面的答案不一定是错误的,它提供了一些额外的见解,因此我将其保留。有关更多信息,请参见此帖子https://davisvaughan.github.io/furrr/articles/articles/gotchas.html#non-standard-evaluation-of-arguments

与purrr不同,使用furrr时,每个参数都必须提前进行一次评估才能将其交付给工人。这意味着使用NSE的参数存在一些差异。实际上,您可以通过以下方法解决此问题:首先使用enquo()分解参数,然后使用!!强制在furrr函数中对其求值。提前解散它们将var1var2变成可以运送给工人的物品。

input <- list(
  element1 = tibble::tibble(a = c(1,var2) {
  var1 <- rlang::enquo(var1)
  var2 <- rlang::enquo(var2)
  
  furrr::future_map_dfr(
    .x = data,.f = ~dplyr::mutate(.x,product = !!var1 * !!var2)
  )
}

future::plan(future::multisession,workers = 2)

multiplier_parallel(input,b)
#> # A tibble: 4 x 3
#>       a     b product
#>   <dbl> <dbl>   <dbl>
#> 1     1     2       2
#> 2     2     2       4
#> 3     1     4       4
#> 4     2     4       8

请注意,我们通常鼓励在{{ }}上使用!!enquo()拥抱模式,但是在像这样的极少数情况下,需要分离化/强制性。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-