Python 我如何划分持有R函数的pyspark RDD

Python 我如何划分持有R函数的pyspark RDD,python,r,apache-spark,pyspark,rpy2,Python,R,Apache Spark,Pyspark,Rpy2,输出 import rpy2.robjects as robjects dffunc = sc.parallelize([(0,robjects.r.rnorm),(1,robjects.r.runif)]) dffunc.collect() 产生相同的错误。R无法在初始化代码之前对代码求值 dffunc = sc.parallelize([(0,robjects.r.rnorm), (1,robjects.r.runif)]).partitionBy(2) def loadmo

输出

import rpy2.robjects as robjects

dffunc = sc.parallelize([(0,robjects.r.rnorm),(1,robjects.r.runif)])
dffunc.collect() 

产生相同的错误。R无法在初始化代码之前对代码求值

dffunc = sc.parallelize([(0,robjects.r.rnorm),     (1,robjects.r.runif)]).partitionBy(2)
def loadmodel(model):
    import rpy2.robjects as robjects
    return model[1](2)
dffunc.map(loadmodel).collect()
正如预期的那样工作。

我想说“这不是rpy2中的一个bug,这是一个特性”,但实际上我必须解决“这是一个限制”

现在发生的是rpy2有2个。一个是低级接口(更接近R的C API),可通过
rpy2.rinterface
获得,另一个是高级接口,具有更多的铃声和口哨,更“pythonic”,并且R对象的类继承自
rinterface
级接口(最后一部分对于下面关于pickle的部分很重要)。导入高级接口会导致在必要时使用默认参数初始化(启动)嵌入式R。导入低级接口
rinterface
没有此副作用,必须显式执行嵌入式R的初始化(函数
initr
)。rpy2是这样设计的,因为嵌入式R的初始化可以有参数:首先导入
rpy2.rinterface
,设置初始化,然后导入
rpy2.robjects
,这样做是可能的

此外,由rpy2包装的R对象的序列化(pickle)目前仅在
rinterface
级别定义(请参阅)。Pickling
robjects
-级别(高级)rpy2对象正在使用
rinterface
-级别代码,取消pickle时,它们将保持在较低级别(Python pickle包含对象类在其中定义的模块,并将导入该模块-此处
rinterface
,这并不意味着嵌入式R的初始化)。采用这种方式的原因很简单,就是它“现在已经足够好了”:在实现时,我必须同时想到一种连接两种不同语言的好方法,并通过Python C-API和pickling/unpickling Python对象来学习

dffuncpickle = sc.parallelize([(0,pickle.dumps(robjects.r.rnorm)),(1,pickle.dumps(robjects.r.runif))]).partitionBy(2)
def loadmodelpickle(model):
    import rpy2.robjects as robjects
    import pickle
    return pickle.loads(model[1])(2)
dffuncpickle.map(loadmodelpickle).collect()

在取消pickle之前,这一点从未被重新讨论过。据我所知,rpy2的pickle使用的是Python的
多处理
(并且在初始化子进程的代码中添加类似于import语句的内容是一种廉价且足够的修复方法)。现在是再次查看此问题的时候。如果需要,请为rpy2提交错误报告

编辑:这无疑是rpy2的一个问题。pickled
robjects
-级别的对象应该解压回
robjects
-级别,而不是
rinterface
-级别。我已经打开了一个(并且已经在默认/dev分支中推送了一个基本补丁)


第二次编辑:该补丁是从2.7.7版开始发布的rpy2的一部分(撰写本文时的最新版本为2.7.8).

我认为这个问题更微妙。您需要一个活动的R会话,其中数据被取消pickle。它可能是真的,也可能不是真的,这取决于时间。就我个人而言,我会避免在R对象上传递R对象/或视图。@zero323也许我可以结合使用python在内存中的pickle-
pickle.dumps
?感谢您的精彩解释我没有完全理解关键的最后一点:
和添加导入,或者调用rinterface.initr()这是一个廉价且足够的修复程序
。您指的是什么导入?最后,在何种情况下,我应该提交一份错误报告?正如您所指出的,这一部分不是最清晰的。我编辑它是为了改进它。这就是您的函数loadmodelpickle。此修补程序非常有效。期待下一个版本e、 感谢您对该软件包所做的大量工作,文档非常棒。
RuntimeError: ('R cannot evaluate code before being initialized.', <built-in function unserialize>
dffunc = sc.parallelize([(0,robjects.r.rnorm),     (1,robjects.r.runif)]).partitionBy(2)
def loadmodel(model):
    import rpy2.robjects as robjects
    return model[1](2)
dffunc.map(loadmodel).collect()
dffuncpickle = sc.parallelize([(0,pickle.dumps(robjects.r.rnorm)),(1,pickle.dumps(robjects.r.runif))]).partitionBy(2)
def loadmodelpickle(model):
    import rpy2.robjects as robjects
    import pickle
    return pickle.loads(model[1])(2)
dffuncpickle.map(loadmodelpickle).collect()
import rpy2.robjects
import rpy2.rinterface
rpy2.rinterface.initr()