库加载不扩展到Spark中的函数

时间:2017-11-07 16:43:47

标签: r apache-spark scope sparkr

我有一个SparkR脚本,可以加载一些库,还可以定义其他源脚本的函数。它的头部看起来像这样:

library(SparkR, lib.loc = c(file.path(Sys.getenv("SPARK_HOME"), "R", "lib"))) 
library(devtools)   
library(JC.utilities)         # user-created

source("path/to/clean_data.R")

其中clean_data.R使用JM.utilities库中的某些函数,如下所示:

clean_data <- function(df) {
  ... 
  return(JC.utilities::reformat(df))
}

在基础R中,这没有问题,因为通过获取定义了此函数的R脚本应该意味着库和函数现在处于相同的范围内。但在Spark中,当我调用clean_data()时,我收到此错误消息:

Error in loadNamespace(name) : there is no package called ‘JM.utilities’

两个问题:

  1. 为什么Spark似乎没有记住我已经加载了这个库?
  2. 是否可以解决此问题,而无需明确定义一堆内容?

1 个答案:

答案 0 :(得分:1)

您已在驱动程序上加载库,但未在处理单独工作区的执行程序上加载。

您需要在应用于数据框的函数中导入JC.utilities。

如果执行者上没有安装库,则需要执行此操作,或者您可以尝试执行this

我设计了一个最小的例子,用库字符串及其函数str_length来说明我的观点:

> d<-data.frame(a=c("a", "abcd", "bb"), b=c(1,2,3))
> df <- as.DataFrame(d)

让我们尝试看看它是否适用于基本R代码:

> dapplyCollect(df, function(x) {cbind(x$a, x$b, x$b*x$b+1) })
    [,1]   [,2] [,3] 
[1,] "a"    "1"  "2"  
[2,] "abcd" "2"  "5"  
[3,] "bb"   "3"  "10" 

有效!然后让我们尝试计算第一列的字符数(我可以使用nchar,但想法是演示如何使用库)。

> import(stringr)
> str_length("abcdef")
[1] 4

它在驱动程序中工作正常。让我们尝试一下spark:

> dapplyCollect(df, function(x) {cbind(x$a, x$b, x$b*x$b+1, str_length(x$a)) })
17/11/08 18:55:17 ERROR executor.Executor: Exception in task 0.0 in stage 10.0 (TID 10)
org.apache.spark.SparkException: R computation failed with
 Error in cbind(x$a, x$b, x$b * x$b + 1, str_length(x$a)) : 
  could not find function "str_length"

正如我所解释的那样,在驱动程序中导入库不会将其导入到worker中。然而,那就是我需要的地方。现在让我们在dapply中导入库:

> dapplyCollect(df, function(x) {library(stringr); cbind(x$a, x$b, x$b*x$b+1, str_length(x$a)) })
     [,1]   [,2] [,3] [,4]
[1,] "a"    "1"  "2"  "1" 
[2,] "abcd" "2"  "5"  "4" 
[3,] "bb"   "3"  "10" "2"

然后你去。