Как создать New Rdd со всеми возможными комбинациями элементов других Rdd в pyspark? - PullRequest
0 голосов
/ 03 декабря 2018

Привет, я создал Rdd, как показано ниже

rdd1=sc.parallelize(['P','T','K'])
rdd1.collect()
['P', 'T', 'K']

Теперь я хочу создать новый RDD2 со всеми возможными комбинациями, как показано ниже, с новым RDD.ie, за исключением такой же комбинации элементов, как (p, p),(k, k), (t, t).

мой ожидаемый результат, когда я делаю

RDD2.collect()

[
    ('P'),('T'),('K'),
    ('P','T'),('P','K'),('T','K'),('T','P'),('K','P'),('K','T'),
    ('P','T','K'),('P','K','T'),('T','P','K'),('T','K','P'),('K','P','T'),('K','T','P')
]

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

Кажется, что вы хотите сгенерировать все перестановки элементов в rdd, где каждая строка содержит уникальные значения.

Один из способов - сначала создать вспомогательную функцию для генерации желаемой комбинации длиныn:

from functools import reduce
from itertools import chain

def combinations_of_length_n(rdd, n):
    # for n > 0
    return reduce(
        lambda a, b: a.cartesian(b).map(lambda x: tuple(chain.from_iterable(x))),
        [rdd]*n
    ).filter(lambda x: len(set(x))==n)

По сути, функция будет делать n декартовы произведения вашего rdd с собой и сохранять только те строки, в которых все значения различны.

Мыможете проверить это для n = [2, 3]:

print(combinations_of_length_n(rdd1, n=2).collect())
#[('P', 'T'), ('P', 'K'), ('T', 'P'), ('K', 'P'), ('T', 'K'), ('K', 'T')]

print(combinations_of_length_n(rdd1, n=3).collect())
#[('P', 'T', 'K'),
# ('P', 'K', 'T'),
# ('T', 'P', 'K'),
# ('K', 'P', 'T'),
# ('T', 'K', 'P'),
# ('K', 'T', 'P')]

Конечный результат, который вам нужен, это просто union из этих промежуточных результатов с исходным rdd (со значениями, сопоставленными с tuple s),

rdd1.map(lambda x: tuple((x,)))\
    .union(combinations_of_length_n(rdd1, 2))\
    .union(combinations_of_length_n(rdd1, 3)).collect()
#[('P',),
# ('T',),
# ('K',),
# ('P', 'T'),
# ('P', 'K'),
# ('T', 'P'),
# ('K', 'P'),
# ('T', 'K'),
# ('K', 'T'),
# ('P', 'T', 'K'),
# ('P', 'K', 'T'),
# ('T', 'P', 'K'),
# ('K', 'P', 'T'),
# ('T', 'K', 'P'),
# ('K', 'T', 'P')]

Обобщение для любого максимального числа повторений:

num_reps = 3
reduce(
    lambda a, b: a.union(b),
    [
        combinations_of_length_n(rdd1.map(lambda x: tuple((x,))), i+1) 
        for i in range(num_reps)
    ]
).collect()
#Same as above

Примечание : декартовы произведения являются дорогостоящими операциями, и их следует избегатькогда это возможно.

0 голосов
/ 03 декабря 2018

Есть несколько способов.Вы можете запустить цикл, получить перестановки и сохранить их в списке, а затем преобразовать список в rdd

>>> rdd1.collect()
['P', 'T', 'K']
>>> 
>>> l = []
>>> for i in range(2,rdd1.count()+1):
...     x = list(itertools.permutations(rdd1.toLocalIterator(),i))
...     l = l+x
... 
>>> rdd2 = sc.parallelize(l)
>>> 
>>> rdd2.collect()
[('P', 'T'), ('P', 'K'), ('T', 'P'), ('T', 'K'), ('K', 'P'), ('K', 'T'), ('P', 'T', 'K'), ('P', 'K', 'T'), ('T', 'P', 'K'), ('T', 'K', 'P'), ('K', 'P', 'T'), ('K', 'T', 'P')]
...