我希望underscores
/ combineByKey
/ reduceByKey
中的逻辑依赖于当前正在操作的密钥。从方法签名我可以看出,传递给这些方法的唯一参数是组合/缩小/折叠的值。
使用一个简单的例子,我只有一个foldByKey
元组的RDD,我想要的结果是由(int, int)
键控的rdd,其中值是最接近键的tuple[0]
例如:
int
应减少到:
(1, 8)
(1, 3)
(1, -1)
(2, 4)
(2, 5)
(2, 2)
(3, 2)
(3, 4)
请注意,在比较(1, 3)
(2, 2)
(3, 2)
和(1, 3)
时,我并不关心选择哪一个,因为它们的距离都相同。对于" 3"键。
我想象这样做的方式将是:
(1, -1)
但rdd.reduceByKey(lambda key, v1, v2: v1 if abs(key - v1) < abs(key - v2) else v2)
函数只需要2个参数:要合并的两个值。似乎最简单的方法是在我的reducer中引用键来实现我的目标;这有可能吗?
如果我试试这个,我会收到错误:
reduce
TypeError :()需要3个参数(给定2个)
我并不是在寻找这个示例问题的解决方案。我想知道的是,有没有理由将密钥传递给rdd = sc.parallelize([(1, 8), (1, 3), (1, -1), (2, 4), (2, 5), (2, 2), (3, 2), (3, 4)])
rdd.reduceByKey(lambda key, v1, v2: v1 if abs(key - v1) < abs(key - v2) else v2).collect()
函数?我认为这是我缺少的map-reduce哲学的一些基本原则。
注意我可以通过插入一个映射步骤来解决我的例子,该步骤将每个值映射到一个元组,该元组由值和距键的距离组成:
reduceByKey
答案 0 :(得分:0)
我认为没有强有力的理由不传递密钥
但是,我觉得reduceByKey
API是针对常见用例设计的 - 计算每个键值的总和。到目前为止,我从未在值计算中需要键。但那只是我的意见。
您解决的问题似乎也是简单的聚合问题。 min()
和groupByKey
可以找到答案。我知道你不是在寻找解决方案,但这就是我写作的方式。
from pyspark import SparkContext
sc = SparkContext()
rdd = sc.parallelize([(1, 8), (1, 3), (1, -1), (2, 4), (2, 5), (2, 2), (3, 2), (3, 4)])
reduced = rdd.groupByKey().map(lambda (k, v): (k, min(v, key=lambda e:abs(e-k))))
print(reduced.collectAsMap())
结果
{1: 3, 2: 2, 3: 2}