将自定义函数应用于数据类型数据集

时间:2017-09-22 09:35:15

标签: python pyspark spark-dataframe rdd

我有一个名为'counts'的列的数据框,我想将自定义函数“do_something”应用于列的每个元素,即每个数组。我不想修改数据帧,我只想对列计数进行单独的操作。列的所有数组都具有相同的大小。

+----------------------+---------------------------------------+
|id|              counts|
+----------------------+---------------------------------------+
|1|          [8.0, 2.0, 3.0|
|2|          [1.0, 6.0, 3.0|                
+----------------------+---------------------------------------+

当我尝试这个时:

df.select('counts').rdd.foreach(lambda x: do_something(x))

即使我尝试没有lambda也会出现同样的错误。

它在

上面的行上失败了
  

Py4JJavaError Traceback(最近一次调用   最后)in()   ----> 1 df.select('counts')。rdd.foreach(lambda x:do_something(x))

     在foreach中的/usr/hdp/2.5.3.0-37/spark/python/pyspark/rdd.py(self,f)       745 f(x)       746返回iter([])    - > 747 self.mapPartitions(processPartition).count()#强制评估       748       749 def foreachPartition(self,f):

     

/usr/hdp/2.5.3.0-37/spark/python/pyspark/rdd.py in count(self)1002   3 1003“”“    - > 1004返回self.mapPartitions(lambda i:[sum(1 for _ in i)])。sum()1005 1006 def stats(self):

     

/usr/hdp/2.5.3.0-37/spark/python/pyspark/rdd.py in sum(self)       993 6.0       994“”“    - > 995返回self.mapPartitions(lambda x:[sum(x)])。fold(0,operator.add)       996       997 def count(self):

     

/usr/hdp/2.5.3.0-37/spark/python/pyspark/rdd.py in fold(self,   zeroValue,op)       提供给每个分区的867#zeroValue与提供的分区是唯一的       868#到最后减少通话    - > 869 vals = self.mapPartitions(func).collect()       870 return reduce(op,vals,zeroValue)       871

     

/usr/hdp/2.5.3.0-37/spark/python/pyspark/rdd.py in collect(self)       769“”“       770使用SCCallSiteSync(self.context)作为css:    - > 771 port = self.ctx._jvm.PythonRDD.collectAndServe(self._jrdd.rdd())       772返回列表(_load_from_socket(port,self._jrdd_deserializer))       773

     

/usr/hdp/2.5.3.0-37/spark/python/lib/py4j-0.9-src.zip/py4j/java_gateway.py   在调用(self,* args)       811回答= self.gateway_client.send_command(命令)       812 return_value = get_return_value(    - > 813回答,self.gateway_client,self.target_id,self.name)       814       815用于temp_args中的temp_arg:

     

/usr/hdp/2.5.3.0-37/spark/python/pyspark/sql/utils.py in deco(* a,   ** KW)        43 def deco(* a,** kw):        44尝试:   ---> 45返回f(* a,** kw)        46除了py4j.protocol.Py4JJavaError为e:        47 s = e.java_exception.toString()

     

/usr/hdp/2.5.3.0-37/spark/python/lib/py4j-0.9-src.zip/py4j/protocol.py   在get_return_value中(answer,gateway_client,target_id,name)       306引发Py4JJavaError(       307“调用{0} {1} {2}时发生错误。\ n”。    - > 308格式(target_id,“。”,名称),值)       309其他:       310引发Py4JError(

尽管所有输入数组都具有相同的大小。

big_list=[]
def do_something(i_array):
    outputs = custom_library(i_array) # takes as input an array and returns 3 new lists
    big_list.extend(outputs)

1 个答案:

答案 0 :(得分:2)

你的UDF修改了一个python对象,即:

  • 在数据框外部,即使功能有效,您也无法访问该值,因为您没有将其返回到数据框的行
  • 很大,它的元素数量至少是数据框中行数的三倍

您可以尝试这样做:

def do_something(i_array):
    outputs = custom_library(i_array)
    return outputs

import pyspark.sql.functions as psf
do_something_udf = psf.udf(do_something, ArrayType(ArrayType(DoubleType()))

DoubleType()或您返回的任何类型

df.withColumn("outputs", psf.explode(do_something_udf("count")))

您的行数是df

的三倍