Pyspark在一行中多次使用groupByKey / mapValues

时间:2016-12-09 14:35:00

标签: apache-spark pyspark rdd

我正在使用PySpark,我正在寻找一种方法来使用多个groupByKey / mapValues方法。

鉴于:

rdd = sc.parallelize([(u'04896f3765094732a478ba63dd42c785', 
                       u'2016-01-01', 
                       u'2', 
                       u'1404.0', 
                       u'2016-333', 
                       u'2016-48', 
                       u'2016-11', 
                        '2016-11-28'),

                      (u'kldmm584753dljkdhggdklkfj32a478ba63dd422574', 
                       u'2016-01-14', 
                       u'6', 
                       u'2000.0', 
                       u'2016-333', 
                       u'2016-48', 
                       u'2016-11', 
                        '2016-11-28')

                    ])

我想用第4个元素('2016-333'这里)对我的rdd进行分组,得到len,sum等。 我的代码:

(rdd
 .map(lambda x : (x[4], x[0]))
 .groupByKey()
 .mapValues(len)
 .collect())

Output : [(u'2016-333', 2)]

(rdd
 .map(lambda x : (x[4], float(x[3])))
 .groupByKey()
 .mapValues(sum)
 .collect())

Output : [(u'2016-333', 3404.0)]

(rdd
 .map(lambda x : (x[4], int(x[2])))
 .groupByKey()
 .mapValues(sum)
 .collect())

Output : [(u'2016-333', 8)]

我的问题:有没有办法一次性完成这项工作? 预期的输出是:

[(u'2016-333', 2, 3404.0, 8)]

Thx!

2 个答案:

答案 0 :(得分:3)

您可以在wordcount example中使用reduceByKey。在这里,你的值是一个由3部分组成的元组,你的reducer将是元素的总和。

rdd.map(lambda x: (x[4], (1, float(x[3]), int(x[2])))).reduceByKey(lambda x,y: (x[0] + y[0], x[1] + y[1], x[2] + y[2])).collect()

答案 1 :(得分:1)

最简单的可能:

rdd.map(lambda x: (x[4], float(x[3]), int(x[2]))).toDF(["key", "x3", "x2"]) \
    .groupBy("key").agg({"*": "count", "x3": "sum", "x2": "sum"}).rdd

rdd.map(lambda x: (x[4], np.array([1, float(x[3]), int(x[2])]))) \
    .reduceByKey(lambda x, y: x + y) \
    .mapValues(lambda x: (int(x[0]) , int(x[1]), x[2]))