从平均每行150个属性的多个csv文件中,我需要在pyspark中满足此SQL请求:
SELECT object_id, COUNT(*), MAX(source_id), MIN(ra), MAX(ra), MIN(decl), MAX(decl)
我使用了一个map函数,它接受每一行,过滤并输出所需的字段:
Map Output : < object_id , Array( objectid , 1,sourceid,ra,decl] ) >
我使用了一个reduce函数,它一次计算所有必需的聚合函数(A和B是数组,如地图输出中所述):
def generalReduce(A,B):
myarrayRet = [0,0,0,0,0,0,0]
myarrayRet[0] = A[0]
#count
myarrayRet[1] = A[1] + B[1]
#maxSrcId
myarrayRet[2] = A[2] if A[2] > B[2] else B[2]
#minRa
myarrayRet[3] = A[3] if A[3] < B[3] else B[3]
#maxRa
myarrayRet[4] = A[3] if A[3] > B[3] else B[3]
#minDecl
myarrayRet[5] = A[4] if A[4] > B[4] else B[4]
#maxDecl
myarrayRet[6] = A[4] if A[4] > B[4] else B[4]
return myarrayRet
问题是,有些键只有1个值,因此reduce阶段输出4个阵列的数组。这让我觉得只有当键的值超过1时才调用reduce函数,我错了吗?如果没有,如果每个键只有一个值,我该如何输出自定义值?
谢谢。
答案 0 :(得分:1)
我不确定我是否正确理解你的问题。如果你有像data
这样的键值RDD,如下所示:
Map Output : < object_id , Array( objectid , 1,sourceid,ra,decl] ) >
使用data.reduceByKey(generalReduce)
,你的函数generalReduce应该是可交换的和关联的。也就是说,如果您有三个元素,generalReduce(generalReduce(elem1,elem2),elem3)
应该等于generalReduce(elem1,generalReduce(elem2,elem3)
。在您的代码中,generalReduce(elem1,elem2)
的返回值与elem3
的类型不同,因此您应该考虑到这一点。事实上,我不认为你的代码正在做你打算做的事情。
对于您的第二个问题,如果您想要这样做,您可以使用地图以正确的格式转换值。