J'ai un cadre de données qui comporte une ligne et plusieurs colonnes. Certaines de ces colonnes sont des valeurs individuelles, d'autres des listes. Toutes les colonnes de liste ont la même longueur. Je veux diviser chaque colonne de liste en une ligne distincte, tout en conservant telle quelle les colonnes qui ne sont pas des listes.
Exemple DF :
from pyspark import Row
from pyspark.sql import SQLContext
from pyspark.sql.functions import explode
sqlc = SQLContext(sc)
df = sqlc.createDataFrame([Row(a=1, b=[1,2,3],c=[7,8,9], d='foo')])
# +---+---------+---------+---+
# | a| b| c| d|
# +---+---------+---------+---+
# | 1|[1, 2, 3]|[7, 8, 9]|foo|
# +---+---------+---------+---+
Ce que je veux :
+---+---+----+------+
| a| b| c | d |
+---+---+----+------+
| 1| 1| 7 | foo |
| 1| 2| 8 | foo |
| 1| 3| 9 | foo |
+---+---+----+------+
Si je n'avais qu'une seule colonne de liste, ce serait facile en faisant simplement un explode
:
df_exploded = df.withColumn('b', explode('b'))
# >>> df_exploded.show()
# +---+---+---------+---+
# | a| b| c| d|
# +---+---+---------+---+
# | 1| 1|[7, 8, 9]|foo|
# | 1| 2|[7, 8, 9]|foo|
# | 1| 3|[7, 8, 9]|foo|
# +---+---+---------+---+
Cependant, si j'essaie également de explode
el c
je me retrouve avec un cadre de données dont la longueur est le carré de ce que je veux :
df_exploded_again = df_exploded.withColumn('c', explode('c'))
# >>> df_exploded_again.show()
# +---+---+---+---+
# | a| b| c| d|
# +---+---+---+---+
# | 1| 1| 7|foo|
# | 1| 1| 8|foo|
# | 1| 1| 9|foo|
# | 1| 2| 7|foo|
# | 1| 2| 8|foo|
# | 1| 2| 9|foo|
# | 1| 3| 7|foo|
# | 1| 3| 8|foo|
# | 1| 3| 9|foo|
# +---+---+---+---+
Ce que je veux, c'est - pour chaque colonne, prendre le nième élément du tableau dans cette colonne et l'ajouter à une nouvelle ligne. J'ai essayé de mapper un explode sur toutes les colonnes du cadre de données, mais cela ne semble pas fonctionner non plus :
df_split = df.rdd.map(lambda col: df.withColumn(col, explode(col))).toDF()