在pyspark中获取RDD中每个键的所有可能值组合

时间:2015-05-20 01:58:23

标签: apache-spark combinations itertools pyspark

我正在努力实现我认为应该非常简单但我无法通过思考,因​​此需要一些帮助。

我有一个RDD,我有:

  key1, (val_id1,val11), (val_id2,val12),(val_id3,val13) ...
  key2, (val_id5,val25), (val_id7,val27), (val_id2,val22) ...
  ...

我想为每个键,所有值对的组合使得值元组中的第二个元素在输出之前相乘。例如:

上面key1的值产生的输出是:

((val_id1,val_id2), val11 * val12) , ((val_id1,val_id3),val11 * val13) , ((val_id2,val_id3),val12 * val13) ...

我知道itertools包中有一个itertools.combinations模块,但我不知道如何将它完全合并到RDD的上下文中。任何帮助将非常感激。

3 个答案:

答案 0 :(得分:2)

假设原始RDD是文本格式。以下代码尚未在spark上运行,但解决方案应该是这样的。

from itertools import combinations
import re

def clean(dirtyRecord):
    """
    Accept a String value "key1, (val_id1,key11), (val_id2,key22), ..."
    and convert it into record of the form
    [key1, [(val_id1, key11), (val_id2, key12), ... ]]
    """

    splitRecord = dirtyRecord.split(', ')
    # The splitRecord[0] is the 'key'
    splits = [re.search('\((\w+),(\w+)\)', tuples).groups() for tuples in splitRecord[1:]]

    updateSplitsWithFloat = []
    for item in splits:
        updateSplitsWithFloat.append((item[0], float(item[1]))

    splits = splitRecord[0] + updateSplitsWithFloat

    return splits

def genCombinations(features):
    """
    Accept a list [(val_id1, key11), (val_id2, key12), ... ]
    and generate the output asked in question
    """

    val_ids, vals = zip(*features)
    val_ids = combinations(val_ids, repeat=2)
    vals = map(lambda x: x[0] * x[1], combinations(vals, repeat=2))

    return [(t0, t1) for t0, t1 in zip(val_ids, vals)]

# Begin processing the original data
valuesPerKeyRDD = (originalRawRDD
                   .map(lambda x: clean(x))
                   .map(lambda x: (x[0], genCombinations(x[1])))
                   .cache())

答案 1 :(得分:0)

这是函数(它假设内部集合是字典,因为它们应该是。但是如果你没有它,你总是可以将.keys()函数替换为你需要循环遍历内部元组列表的地方。拿回钥匙)

def get_res(tup):
       based_dict = tup[1]
       k = tup[0]
       generated_tupes = []
       for comb in itertools.combinations(based_dict.keys(),2):
             value = str(based_dict[comb[0]])+"**"+str(based_dict[comb[1]])
             generated_tupes.append((comb,value))
       return (k,generated_tupes)

你可以在没有火花的情况下进行测试:

>>> based
[('k1', {'id2': 12, 'id3': 13, 'id1': 11}), ('k2', {'id4': 24, 'id5': 25})]

>>> transformed = map(get_res,based)
>>> transformed
[('k1', [(('id2', 'id3'), '12**13'), (('id2', 'id1'), '12**11'), (('id3', 'id1'), '13**11')]), ('k2', [(('id4', 'id5'), '24**25')])]

在你的火花代码中,只需调用rdd.map(get_res)

即可

答案 2 :(得分:0)

我已经制定了此算法,但是使用更高的数字似乎无法正常工作或运行速度很慢,它将在大数据集群(cloudera)中运行,因此我认为我必须将函数放入pyspark ,请帮忙。

将熊猫作为pd导入 将itertools导入为its

number_list = [10953,10423,10053]

def reducer(nums):   定义范围(n):     打印(n)     返回范围(n,-1,-1)

num_list = list(map(ranges,nums))   返回列表(itts.product(* num_list))

data = pd.DataFrame(reducer(number_list)) 打印(数据)