PySpark reduceByKey仅需一个键

时间:2018-08-23 14:04:31

标签: python python-3.x apache-spark pyspark

我有一个这样的rdd

// Structure List[Tuple(x1, x2, value), Tuple(x1, x2, value)]
data = [('23', '98', 34), ('23', '89', 39), ('23', '12', 30), ('24', '12', 34), ('24', '14', 37), ('24', '16', 30)]

我正在寻找最终结果是x1得分的最大值,并将x2值与其关联。像这样

data = [('23', '89', 39), ('24', '14', 37)]

我尝试了reduceByKey,但它给了我每种组合的最大值,这不是我想要的。

来自comment

这是我尝试过的:

max_by_group = (
    data.map(lambda x: (x[0], x))
        .reduceByKey(lambda x1, x2: max(x1, x2, key=lambda x: x[-1])) 
        .values()
)

3 个答案:

答案 0 :(得分:3)

groupBy第一个元素,然后通过元组中的第三个元素找到每个组的最大值:

(rdd.groupBy(lambda x: x[0])
    .mapValues(lambda x: max(x, key=lambda y: y[2]))
    .values()
).collect()
# [('24', '14', 37), ('23', '89', 39)]

或使用reduceByKey

(rdd.map(lambda x: (x[0], x))
    .reduceByKey(lambda x, y: x if x[2] > y[2] else y)
    .values()
).collect()
# [('24', '14', 37), ('23', '89', 39)]

答案 1 :(得分:2)

@Psidom的答案是如果您使用rdd,那么您正在寻找什么。另一种选择是convert your rdd to a DataFrame

rdd = sc.parallelize(data)
df = rdd.toDF(["x1", "x2", "value"])
df.show()
#+---+---+-----+
#| x1| x2|value|
#+---+---+-----+
#| 23| 98|   34|
#| 23| 89|   39|
#| 23| 12|   30|
#| 24| 12|   34|
#| 24| 14|   37|
#| 24| 16|   30|
#+---+---+-----+

现在您可以group by x1 and filter the rows with the maximum value

import pyspark.sql.functions as f
from pyspark.sql import Window
w = Window.partitionBy('x1')
df.withColumn('maxValue', f.max('value').over(w))\
    .where(f.col('value') == f.col('maxValue'))\
    .drop('maxValue')\
    .show()
#+---+---+-----+
#| x1| x2|value|
#+---+---+-----+
#| 23| 89|   39|
#| 24| 14|   37|
#+---+---+-----+

答案 2 :(得分:0)

从itertools导入分组依据:

[max(list(j),key=lambda x:x[2]) for i,j in groupby(data,key = lambda x:x[0])]

Out[335]: [('23', '89', 39), ('24', '14', 37)]