2016-05-19 4 views
0

My DataFrame df имеет столбец, действующий как внешний ключ, к таблице, которая является много-к-одному с df. Для каждого уникального значения внешнего ключа, он содержит еще один внешний ключ, но только один раз, причем все более значений в этой группе порожняком:PySpark DataFrame reduce_by

df.filter(df.foreignkey1 == "12345").select("foreignkey1", "foreignkey2").show() 

+-----------+-----------+ 
|foreignkey1|foreignkey2| 
+-----------+-----------+ 
|  12345|   | 
|  12345|   | 
|  12345|   | 
|  12345| 100002020| 
|  12345|   | 
+-----------+-----------+ 

Здесь я выбрал все записи, где foreignkey1 12345, и отобразили рядом с ними значения foreignkey2.

Я хотел бы, чтобы свернуть это вниз к этому:

+-----------+-----------+ 
|foreignkey1|foreignkey2| 
+-----------+-----------+ 
|  12345| 100002020| 
+-----------+-----------+ 

В теории, должен быть только один foreignkey2 за уникальную ценность foreignkey1, хотя часть этого тестирования, что.

Я довольно новичок в Спарке, и это кажется хорошим местом для того, чтобы спросить других, чтобы я следил за «искровым мышлением». Любая помощь приветствуется. Является ли мой лучший вариант df.rdd.reduceByKey или есть ли еще более интеллектуальный способ сделать это, используя функции groupby и aggregate? Благодаря !

+0

Просто подумал: Я мог бы, вероятно, просто 'dropna()' и посмотреть, если это больше, чем число уникальных значений в 'foreignkey1'. Однако это не гарантирует, что есть один 'foreignkey2' за' foreignkey1', хотя он, возможно, сильно указывает его. – Quentin

ответ

1

Я думаю, что это может сделать трюк:

df.groupBy("fk").agg(max("fk2")) 

Он будет возвращать только две колонки: fk и max(fk2). Второй столбец будет иметь наибольшее значение для fk2 для каждого значения fk.

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

df.select("fk", "fk2").filter(col("fk2").isNotNull()) 

В противном случае, если может быть больше чем один fk2 на fk, вы можете попробовать слияние обоих подходов, как попытку улучшить производительность:

df.select("fk", "fk2").filter(col("fk2").isNotNull()).groupBy("fk").agg(max("fk2")) 
+0

Второй подход намного лучше, если предположения Даниила верны, с точки зрения эффективности. – David

+0

Спасибо, хорошее решение. Что касается проверки того, что у меня есть одна к одной карте между моими FK, второй фрагмент будет полезен: после его запуска я могу сравнить количество строк в этом DF с количеством уникальных значений fk1. – Quentin

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