Я написал решение вашей проблемы, используя UDF для панд.Я не понял, почему ваш столбец field_a (представляющий пол?) Был списком, поэтому я превратил его в простую строку, но вы можете сделать это списком строк, если хотите.Вот оно:
(1) Создайте фиктивную df в пандах и создайте искру DataFrame:
import pandas as pd
import random
from pyspark.sql.functions import pandas_udf, PandasUDFType
a_list = ['F', 'M']
b_list = ['IDN', 'IND', 'SGP', 'BHR', 'MYS', 'PHL', 'AUS', 'SAU', 'KWT']
size = 10
dummy_df = pd.DataFrame({'docId': [random.randint(0,100) for _ in range(size)],
'field_b': [[random.choice(b_list), random.choice(b_list)] for _ in range(size)],
'field_a': [random.choice(a_list) for _ in range(size)]})
df = spark.createDataFrame(dummy_df)
производя:
+-----+-------+----------+
|docId|field_a| field_b|
+-----+-------+----------+
| 23| F|[SAU, SGP]|
| 36| F|[IDN, PHL]|
| 82| M|[BHR, SAU]|
| 30| F|[AUS, IDN]|
| 75| F|[AUS, MYS]|
| 46| F|[SAU, IDN]|
| 11| F|[SAU, BHR]|
| 71| M|[KWT, IDN]|
| 50| F|[IND, SGP]|
| 78| F|[IND, SGP]|
+-----+-------+----------+
(2) Затем определите пандUDF, сгруппировать и применить:
@pandas_udf('field_a string, set_field_b array<string>', PandasUDFType.GROUPED_MAP)
def my_pandas_udf(df):
unique_values = pd.DataFrame(df['field_b'].values.tolist()).stack().unique().tolist()
return pd.DataFrame({'field_a': df['field_a'].iloc[0], 'set_field_b': [unique_values]})
result = df.groupby('field_a').apply(my_pandas_udf)
, чтобы получить конечный результат:
+-------+--------------------+
|field_a| set_field_b|
+-------+--------------------+
| F|[SAU, SGP, IDN, P...|
| M|[BHR, SAU, KWT, IDN]|
+-------+--------------------+
Мне не очень нравится подход панды / толист / стек / уникальный подход, возможно, есть лучшийЭто можно сделать, но обработка списков внутри фреймов данных Pandas, как правило, не проста.
Теперь вам нужно сравнить производительность с подходом explode + groupby + collect_set, не зная, какой из них будет быстрее.Расскажите нам, когда узнаете!