Операция Spark dataframe над списком возвращает [Ljava.яз..Объект;@]


У меня есть фрейм данных pyspark, где я сгруппировал данные в список с помощью collect_list.

from pyspark.sql.functions import udf, collect_list
from itertools import combinations, chain

#Create Dataframe
df = spark.createDataFrame( [(1,'a'), (1,'b'), (2,'c')] , ["id", "colA"])   

df.show()
>>>
+---+----+
| id|colA|
+---+----+
|  1|   a|
|  1|   b|
|  2|   c|
+---+----+

#Group by and collect to list
df = df.groupBy(df.id).agg(collect_list("colA").alias("colAlist"))

df.show()
>>>
+---+--------+
| id|colAList|
+---+--------+
|  1|  [a, b]|
|  2|     [c]|
+---+--------+

Затем я использую функцию, чтобы найти все комбинации элементов списка в новый список

allsubsets = lambda l: list(chain(*[combinations(l , n) for n in range(1,len(l)+1)]))
df = df.withColumn('colAsubsets',udf(allsubsets)(df['colAList']))

Поэтому я бы выделил что-то вроде

+---+--------------------+
| id| colAsubsets        |
+---+--------------------+
|  1|  [[a], [b], [a,b]] |
|  2|  [[b]]             |
+---+--------------------+

Но я получаю:

df.show()
>>>
 +---+--------+-----------------------------------------------------------------------------------------+
|id |colAList|colAsubsets                                                                              |
+---+--------+-----------------------------------------------------------------------------------------+
|1  |[a, b]  |[[Ljava.lang.Object;@75e2d657, [Ljava.lang.Object;@7f662637, [Ljava.lang.Object;@b572639]|
|2  |[c]     |[[Ljava.lang.Object;@26f67148]                                                           |
+---+--------+-----------------------------------------------------------------------------------------+

Есть идеи, что делать? А потом, может быть, как расплющить список на разные строки?

2 3

2 ответа:

Все, что вам нужно сделать, это извлечь элементы из объектов, созданных chain и combinations уплощенным способом

Итак, изменение

allsubsets = lambda l: list(chain(*[combinations(l , n) for n in range(1,len(l)+1)]))

К следующему

allsubsets = lambda l: [[z for z in y] for y in chain(*[combinations(l , n) for n in range(1,len(l)+1)])]

Должен дать вам

+---+---------+------------------+
|id |colA_list|colAsubsets       |
+---+---------+------------------+
|1  |[a, b]   |[[a], [b], [a, b]]|
|2  |[c]      |[[c]]             |
+---+---------+------------------+

Я надеюсь, что ответ будет полезным

Улучшение ответа @RameshMaharjan, чтобы сгладить список в разные строки:

Вы должны использовать explode на массиве. Вы должны перед этим указать тип вашего udf, чтобы он не возвращал StringType.

from pyspark.sql.functions import explode
from pyspark.sql.types import ArrayType, StringType

allsubsets = lambda l: [[z for z in y] for y in chain(*[combinations(l , n) for n in range(1,len(l)+1)])]
df = df.withColumn('colAsubsets', udf(allsubsets, ArrayType(ArrayType(StringType())))(df['colAList']))
df = df.select('id', explode('colAsubsets'))

Результат:

+---+------+
| id|   col|
+---+------+
|  1|   [a]|
|  1|   [b]|
|  1|[a, b]|
|  2|   [c]|
+---+------+