我正在尝试将聚合函数应用于pyspark中的列。上下文是我手头只有Spark 2.2,没有使用向量化pandas_udf
的选择sdt = spark.createDataFrame(zip([random.randint(1,100) for x in range(20)], [random.randint(1,100) for x in range(20)]), schema=['col1', 'col2'])
+----+----+
|col1|col2|
+----+----+
| 19| 51|
| 95| 56|
| 11| 94|
| 80| 99|
| 20| 80|
| 38| 91|
| 18| 88|
| 4| 33|
+----+----+
为了并行化列,我将其转换为rdd
sdt_col_rdd = sc.parallelize(sdt.columns)
使用普通的python函数进行测试可以正常工作,并返回熊猫的数据帧
x = sdt_col_rdd.map(lambda col : (col, pd.DataFrame(np.random.randint(0,100,size=(2, 4)), columns=list('ABCD'))))
y = x.collectAsMap() #collect into dictionary with column names as key
print(y['col1']; print(y['col2']);
A B C D
0 14 55 4 57
1 36 84 53 51
A B C D
0 14 55 4 57
1 36 84 53 51
切换到spark数据框,这也是返回熊猫的df的示例函数,但是处理Spark的df并使用其本机聚合,转换,操作等:
def myFunc(df, c):
#other more processing, aggregation, transformation may be performed here
res = df.agg((F.min(c)-1).alias("min_"+c), (F.max(c)+1).alias("max_"+c)).toPandas()
res["col_name"] = c
return res
函数可以正常运行
myFunc(sdt.select('col1'), 'col1')
min_col1 max_col1 col_name
0 4 100 col1
当我将其放入rdd地图时,就会出现问题,类似于上面所做的
x= sdt_col_rdd.map(lambda col: (col,myFunc(sdt.select(col), col)))
y = x.collectAsMap()
有没有想法如何在Spark中针对并行列而无需 udaf 来实现这种转换/动作?由于庞大的数据集,而且没有利用Spark的功能,Collect_list效率不高。
在处理上述异常期间,发生了另一个异常:
PicklingError Traceback(最近的通话) 最后)在() 1 col_map = sdt_col_rdd.map(lambda col:(col,myFunc(sdt.select(col),col))) ----> 2 y = col_map.collectAsMap()
collectpMap(self)中的/data/2/parcels/SPARK2-2.2.0.cloudera4-1.cdh5.13.3.p0.603055/lib/spark2/python/pyspark/rdd.py 1555 4 1556“”“ -> 1557 return dict(self.collect())1558 1559 def keys(self):
/data/2/parcels/SPARK2-2.2.0.cloudera4-1.cdh5.13.3.p0.603055/lib/spark2/python/pyspark/rdd.py在collect(self)中 794“”“ 795以SCCallSiteSync(self.context)作为CSS: -> 796 sock_info = self.ctx._jvm.PythonRDD.collectAndServe(self._jrdd.rdd()) 797返回列表(_load_from_socket(sock_info,self._jrdd_deserializer)) 798
/data/2/parcels/SPARK2-2.2.0.cloudera4-1.cdh5.13.3.p0.603055/lib/spark2/python/pyspark/rdd.py in _jrdd(self)2440 2441 wrapd_func = _wrap_function(self.ctx,self.func,self._prev_jrdd_deserializer, -> 2442 self._jrdd_deserializer,profiler)2443 python_rdd = self.ctx._jvm.PythonRDD(self._prev_jrdd.rdd(),包装的功能,2444
_wrap_function中的
self.preservesPartitioning)/data/2/parcels/SPARK2-2.2.0.cloudera4-1.cdh5.13.3.p0.603055/lib/spark2/python/pyspark/rdd.py(sc,func,反序列化器,序列化器,分析器)
_prepare_for_python_RDD(sc,command)中的
2373断言序列化器,“序列化器不应为空” 2374
命令=(func,探查器,解串器,序列化器) -> 2375 pickled_command,broadcast_vars,env,include = _prepare_for_python_RDD(sc,command)2376 return sc._jvm.PythonFunction(bytearray(pickled_command),env,includes, sc.pythonExec,2377 sc.pythonVer, broadcast_vars,sc._javaAccumulator)/data/2/parcels/SPARK2-2.2.0.cloudera4-1.cdh5.13.3.p0.603055/lib/spark2/python/pyspark/rdd.py 2359#序列化 命令将被广播2360压缩= CloudPickleSerializer() -> 2361 pickled_command = ser.dumps(命令)2362,如果len(pickled_command)>(1 << 20):#1M 2363# 广播将具有与创建的PythonRDD相同的生命周期
/data/2/parcels/SPARK2-2.2.0.cloudera4-1.cdh5.13.3.p0.603055/lib/spark2/python/pyspark/serializers.py 在转储中(self,obj) 462 463 def dumps(自己,obj): -> 464返回cloudpickle.dumps(obj,2) 465 466
/data/2/parcels/SPARK2-2.2.0.cloudera4-1.cdh5.13.3.p0.603055/lib/spark2/python/pyspark/cloudpickle.py 在转储中(obj,protocol) 702 703 cp = CloudPickler(文件,协议) -> 704 cp.dump(obj) 705 706返回file.getvalue()
/data/2/parcels/SPARK2-2.2.0.cloudera4-1.cdh5.13.3.p0.603055/lib/spark2/python/pyspark/cloudpickle.py 在转储中(self,obj) 160 msg =“无法序列化对象:%s:%s”%(例如,类。名称,emsg) 161 print_exec(sys.stderr) -> 162提高pickle.PicklingError(msg) 163 164 def save_memoryview(self,obj):
PicklingError:无法序列化对象:Py4JError:错误 发生在调用o62。 getstate 时。跟踪:py4j.Py4JException: 方法 getstate ([])在以下位置不存在 py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:318) 在 py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:326) 在py4j.Gateway.invoke(Gateway.java:274)处 py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132) 在py4j.commands.CallCommand.execute(CallCommand.java:79)处 py4j.GatewayConnection.run(GatewayConnection.java:238)在 java.lang.Thread.run(Thread.java:748)
答案 0 :(得分:-1)
似乎您没有注册udf,导入udf函数并按如下所示注册udf,这应该可以。
从pyspark.sql.functions导入*
myFunc = udf(myFunc,StringType())