lan*_*ooo 5 python dataframe apache-spark apache-spark-sql pyspark
我们有一个 pyspark 数据框,其中有多个列,其中包含具有多个值的数组。我们的目标是将这些列的每个值放在几行中,并保留初始的不同列。所以,从这样的事情开始:
data = [
("A", ["a", "c"], ["1", "5"]),
("B", ["a", "b"], None),
("C", [], ["1"]),
]
Run Code Online (Sandbox Code Playgroud)
什么是:
+---+------+------+
|id |list_a|list_b|
+---+------+------+
|A |[a, c]|[1, 5]|
|B |[a, b]|null |
|C |[] |[1] |
+---+------+------+
Run Code Online (Sandbox Code Playgroud)
我们希望最终得到:
+---+----+----+
|id |col |col |
+---+----+----+
|A |a |null|
|A |c |null|
|A |null|1 |
|A |null|5 |
|B |a |null|
|B |b |null|
|C |null|1 |
+---+----+----+
Run Code Online (Sandbox Code Playgroud)
我们正在考虑几种方法:
但所有这些方法都给人一种肮脏、复杂、容易出错且低效的解决方案的感觉。
有谁知道如何以优雅的方式解决这个问题?
小智 2
如果 list_a 和 list_b 列都可以为空,我将在数据集中添加第四个案例
data = [
("A", ["a", "c"], ["1", "5"]),
("B", ["a", "b"], None),
("C", [], ["1"]),
("D", None, None),
]
df = spark.createDataFrame(data,["id","list_a","list_b"])
Run Code Online (Sandbox Code Playgroud)
然后,我将原始 df 分成 3 个(均为空值、list_a 爆炸和 list_b 爆炸)并执行 unionByName
dfnulls = df.filter(col("list_a").isNull() & col("list_b").isNull())\
.withColumn("list_a", lit(None))\
.withColumn("list_b", lit(None))
df1 = df\
.withColumn("list_a", explode_outer(col("list_a")))\
.withColumn("list_b", lit(None))\
.filter(~col("list_a").isNull())
df2 = df\
.withColumn("list_b", explode_outer(col("list_b")))\
.withColumn("list_a", lit(None))\
.filter(~col("list_b").isNull())
merged_df = df1.unionByName(df2).unionByName(dfnulls)
merged_df.show()
+---+------+------+
| id|list_a|list_b|
+---+------+------+
| A| a| null|
| A| c| null|
| B| a| null|
| B| b| null|
| A| null| 1|
| A| null| 5|
| C| null| 1|
| D| null| null|
+---+------+------+
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1295 次 |
| 最近记录: |