PySpark - более эффективный метод подсчета общих элементов - PullRequest
0 голосов
/ 17 декабря 2018

У меня есть два кадра данных, скажем dfA и dfB.
Я хочу взять их пересечение, а затем посчитать количество уникальных user_ids в этом пересечении.

Я пробовал следующее, которое очень медленно и часто вылетает:

dfA.join(broadcast(dfB), ['user_id'], how='inner').select('user_id').dropDuplicates().count()

Мне нужно запустить много таких строк, чтобы получить сюжет.

Как эффективно выполнить такой запрос?

Ответы [ 2 ]

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

Я думаю, вы можете либо выбрать необходимые столбцы до, а затем выполнить объединение.Также было бы полезно переместить dropDuplicates до объединения, так как тогда вы избавитесь от user_ids, которые появляются несколько раз в одном из фреймов данных.

Результирующий запрос может выглядеть следующим образом:

dfA.select("user_id").join(broadcast(dfB.select("user_id")), ['user_id'], how='inner')\
    .select('user_id').dropDuplicates().count()

ИЛИ:

dfA.select("user_id").dropDuplicates(["user_id",]).join(broadcast(dfB.select("user_id")\
    .dropDuplicates(["user_id",])), ['user_id'], how='inner').select('user_id').count()

ИЛИ также должна работать версия с отлично.

dfA.select("user_id").distinct().join(broadcast(dfB.select("user_id").distinct()),\
    ['user_id'], how='inner').select('user_id').count()
0 голосов
/ 17 декабря 2018

Как описано в вопросе, единственная релевантная часть фрейма данных - это столбец user_id (в своем вопросе вы описываете, что вы присоединяетесь к user_id, а затем используете только поле user_id)

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

Для повышения производительности я бы сделал следующее:

  1. Создайте два небольших DF, которые будут содержать только столбец user_id каждого кадра данных
    Это значительно уменьшит размер каждого кадра данных, поскольку он будет содержать только один столбец (только соответствующий столбец)

    dfAuserid = dfA.select("user_id")
    dfBuserid = dfB.select("user_id")
    
  2. Получить distinct (Примечание: оно эквивалентно dropDuplicate() значениям каждого кадра данных
    Это значительно уменьшит размер каждого кадра данныхпоскольку каждый новый кадр данных будет содержать только отдельные значения столбца user_id.

    dfAuseridDist = dfA.select("user_id").distinct()
    dfBuseridDist = dfB.select("user_id").distinct()
    
  3. Выполните join на двух приведенных выше минималистических кадрах данных, чтобыполучить уникальные значения в пересечении

...