将多列分解为pyspark中的行

Explode multiple columns to rows in pyspark

我有以下 spark 数据框。

Name     age     subject        parts
xxxx     21      Maths,Physics  I
yyyy     22      English,French I,II

我正在尝试在主题和部分中分解上述数据框,如下所示。

预期输出:

Name     age     subject        parts
xxxx     21      Maths          I
xxxx     21      Physics        I
yyyy     22      English        I
yyyy     22      English        II
yyyy     22      French         I
yyyy     22      French         II

我尝试对主题和部分使用 array.zip,然后尝试使用临时列展开,但我在只有一个部分的地方得到了空值。

有没有办法在 Pyspark 中实现这个。

您可以将它们分开,然后将它们重新组合在一起[=13​​=]

拆分科目

df1 = (df
    .select('name', 'age', 'subject')
    .withColumn('subject', F.explode(F.split('subject', ',')))
)

# +----+---+-------+
# |name|age|subject|
# +----+---+-------+
# |xxxx| 21|  Maths|
# |xxxx| 21|Physics|
# |yyyy| 22|English|
# |yyyy| 22| French|
# +----+---+-------+

拆分部分

df2 = (df
    .select('name', 'age', 'parts')
    .withColumn('parts', F.explode(F.split('parts', ',')))
)

# +----+---+-----+
# |name|age|parts|
# +----+---+-----+
# |xxxx| 21|    I|
# |yyyy| 22|    I|
# |yyyy| 22|   II|
# +----+---+-----+

重新加入

df1.join(df2, on=['name', 'age'])

# +----+---+-------+-----+
# |name|age|subject|parts|
# +----+---+-------+-----+
# |xxxx| 21|  Maths|    I|
# |xxxx| 21|Physics|    I|
# |yyyy| 22|English|    I|
# |yyyy| 22|English|   II|
# |yyyy| 22| French|    I|
# |yyyy| 22| French|   II|
# +----+---+-------+-----+

我通过将列作为列表传递给 for 循环并分解列表中每个元素的数据框来做到这一点

您只需同时使用 split and explode :

数据样本

df.show()
+----+---+--------------+-----+                                                 
|Name|age|       subject|parts|
+----+---+--------------+-----+
|xxxx| 21| Maths,Physics|    I|
|yyyy| 22|English,French| I,II|
+----+---+--------------+-----+

df.printSchema()
root
 |-- Name: string (nullable = true)
 |-- age: long (nullable = true)
 |-- subject: string (nullable = true)
 |-- parts: string (nullable = true)

数据转换

from pyspark.sql import functions as F

df.withColumn(
    "subject", F.explode(F.split("subject", ","))
).withColumn(
    "parts", F.explode(F.split("parts", ","))
).show()

+----+---+-------+-----+
|Name|age|subject|parts|
+----+---+-------+-----+
|xxxx| 21|  Maths|    I|
|xxxx| 21|Physics|    I|
|yyyy| 22|English|    I|
|yyyy| 22|English|   II|
|yyyy| 22| French|    I|
|yyyy| 22| French|   II|
+----+---+-------+-----+