2016-09-26 3 views
0

Я применяю карту, а затем уменьшаю преобразованиеByKey на RDD, используя pyspark. Я попробовал оба следующий синтаксис, и оба из них, кажется, работают:pyspark: разница между использованием (,) и [,] для парного представления для reducedByKey

случай 1:

my_rdd_out = my_rdd.map(lambda r: [r['my_id'], [[r['my_value']]]])\ 
           .reduceByKey(lambda a, b: a+b)\ 
           .map(lambda r: r[1]) 

случай 2:

my_rdd_out = my_rdd.map(lambda r: (r['my_id'], [[r['my_value']]]))\ 
           .reduceByKey(lambda a, b: a+b)\ 
           .map(lambda r: r[1]) 

г здесь класса from pyspark.sql import Row. В случае 1 пара выходных данных карты находится в скобке; в случае 2 пара выходных данных карты находится в скобках. Хотя обе работы, мне интересно, есть ли разница между использованием [] и() для представления пары, которая позже будет использоваться для reduceByKey? Благодаря!

ответ

1

Разница между tuple и list в python заключается в том, что объект tuple неизменен, поэтому они являются хешируемыми. list объекты не хешируются, так как они могут быть изменены с использованием их ссылки.

В вашем случае вы можете использовать любой из них (или метод reduceByKey не применим как к кортежам, так и к спискам), это просто удобство, чтобы не перебрасывать один в другой, когда вы получаете объект от какого-либо вызывающего объекта (метод требуется только итерация по коллекции, неважно, какая именно коллекция).

здесь реализация reduceByKey снят с here

def reduceByKey(func, iterable): 
    """Reduce by key. 
    Equivalent to the Spark counterpart 
    Inspired by http://stackoverflow.com/q/33648581/554319 
    1. Sort by key 
    2. Group by key yielding (key, grouper) 
    3. For each pair yield (key, reduce(func, last element of each grouper)) 
    """ 
    get_first = lambda p: p[0] 
    get_second = lambda p: p[1] 
    # iterable.groupBy(_._1).map(l => (l._1, l._2.map(_._2).reduce(func))) 
    return map(
     lambda l: (l[0], reduce(func, map(get_second, l[1]))), 
     groupby(sorted(iterable, key=get_first), get_first) 
    ) 

В вашем примере вы имеете tuple(<something>).reduceByKey(lambda <something>). Очевидно, что итерабельным является tuple, а func - это выражение лямбда.

Как вы можете видеть, ввод просто должен быть итерируемым. доступ к индексу даже не требуется.

Вы могли бы пройти set, deque, генераторное понимание, что угодно. Он не содержит преобразования в список или кортеж.

Он даже не должен получать все данные одновременно, только по одному (функции генератора/понимание тоже будут работать): элегантный способ избежать бесполезного создания временных объектов.

Для этого требуется, чтобы iterable выполнялся только один раз в функции, здесь имеет место функция sorted, которая генерирует list.

+0

Так ли сокращениеByKey фактически отбрасывает список до кортежа до выполнения reduceByKey? Какой формат более формальный/стандартный? Благодаря! – Edamame

+1

см. Мое редактирование (для этого потребовалось редактирование). Нет броска. И выберите свой формат в соответствии с удобством. Для кортежей/списков, созданных только для вызова функции, трудно выбрать, я согласен. –

+0

Привет, Жан-Франсуа, спасибо за подробную информацию. Я пытаюсь понять реализацию def reduceByKey (func, iterable). Что должно быть func и iterable в моем примере: reduceByKey (lambda a, b: a + b)? Большое спасибо! – Edamame

Смежные вопросы