我在pySpark中有这样的rdd1 :(请原谅任何轻微的语法错误):
[(id1,(1,2,3)), (id2,(3,4,5))]
我有另一个rdd2持有这样的:(2,3,4)。
现在我想看看rdd2的每个元素在它出现多少个rdd1子列表中,例如:预期产出rdd(或收集清单我不在乎)
(2, [id1]),(3,[id1,id2]),(4,[id2])
这是我到目前为止(注意rdd2必须是行/算法中的第一项)
rdd2.map(lambda x: (x, x in rdd.map(lambda y:y[1])))
即使这样,我只能给出真/假作为对元组的第二项,我可以忍受它,但即使这样也行不通。尝试在rdd1地图的匿名函数内的rdd2上执行映射时失败。
知道如何让这个朝着正确的方向前进吗?
答案 0 :(得分:1)
如果rrd2
相对较小(适合记忆):
pairs1 = rdd1.flatMap(lambda (k, vals): ((v, k) for v in vals))
vals_set = sc.broadcast(set(rdd2.collect()))
(pairs1
.filter(lambda (k, v): k in vals_set.value)
.groupByKey())
如果没有,您可以从前一部分中取pairs1
并使用join:
pairs2 = rdd2.map(lambda x: (x, None))
(pairs2
.leftOuterJoin(pairs1)
.map(lambda (k, (_, v)): (k, v))
.groupByKey())
与往常一样,如果这只是一个中间结构,您应该考虑reduceByKey
,aggregateByKey
或combineByKey
而不是groupByKey
。如果是最终结构,您可以添加.mapValues(list)
。
最后,您可以尝试使用Spark数据框:
df1 = sqlContext.createDataFrame(
rdd1.flatMap(lambda (v, keys): ({'k': k, 'v': v} for k in keys)))
df2 = sqlContext.createDataFrame(rdd2.map(lambda k: {'k': k}))
(df1
.join(df2, df1.k == df2.k, 'leftsemi')
.map(lambda r: (r.k, r.v)).groupByKey())