PySpark聚合和复杂模式

时间:2018-05-15 21:26:17

标签: python apache-spark pyspark rdd

我有一个像这样的Spark数据帧(df1):

deviceid   host      count 
a.b.c.d   0.0.0.0     1
a.b.c.d   1.1.1.1     3
x.y.z     0.0.0.0     2

我想将其转换为像这样的新数据框

deviceid   hosts_counts   
a.b.c.d    [(0.0.0.0,1),(1.1.1.1,3)]
x.y.z      [(0.0.0.0,2)]

我试过的是:

def convertTuple(*data): 
    for k,v in data: 
        return k[0], (k[1],v)  

df2 = df1.map(convertTuple) # zip host and count 

然后:

function countReducer(a,b): 
    return a + b
df3 = df2.reduceByKey(countReducer)

然而,这给了我一个这样的数据框架,我不知道如何去实现我的最终目标:

df3 Screenshot

修改

我设法使用groupbycollect_list来解决此问题。棘手的部分是为了在(host,count)元组上进行聚合,您需要创建一个strcut。这是代码:

df = df1.groupby("deviceid").agg(collect_list(struct("domain","count")).alias("domain_count"))

1 个答案:

答案 0 :(得分:0)

问题是你要将元组连在一起,countReducer不会给你一个元组列表。在Python中:

(1,2) + (3,4) = (1,2,3,4)

您可以做的是将元组转换为元组列表(使用单个元素)。可以使用map

来完成
.map(lambda x: (x[0], [ x[1] ]))

但在这种情况下,最好更改convertTuple函数以返回您想要的内容:

def convertTuple(*data): 
    for k,v in data: 
        return k[0], [(k[1],v)]

作为旁注,看起来您使用的是RDD而不是数据帧。如果您不使用旧的Spark版本,我建议您考虑更改为数据框,因为它们更容易使用。