首页 > 解决方案 > 如何解压缩字符串格式的列表列表?

问题描述

我有一个 PySpark 数据框,其中有一列包含一个字符串类型的 StructField,它具有一个动态长度的列表列表。

df.schema: StructType(List(StructField(id,StringType,true),StructField(recs,StringType,true)))

|id     | recs |

|ABC|[66, [["AB", 10]]]
|XYZ|[66, [["XY", 10], ["YZ", 20]]]
|DEF|[66, [["DE", 10], ["EF", 20], ["FG", 30]]]  

我正在尝试将列表展平为这样的

|id | like_id
|ABC|AB|
|XYZ|XY|
|XYZ|YZ|
|DEF|DE|
|DEF|EF|
|DEF|FG|

我尝试了什么:

我尝试使用数组表达式,它给我一个错误,因为 recs 是 StringType 符合预期

我可以在 pandas 中使用 json 加载和 itertools 来处理这个问题,但是我需要在 spark 中进行这个处理,因为数据帧很大,大约 3000 万,结果是 10 倍。

df["recs"].apply(
        lambda x: [rec_id[0] for rec_id in json.loads(x)[1:][0]]
    )
    for i, row in df.iterrows():
        ....

标签: pythonapache-sparkpysparkapache-spark-sql

解决方案


如果您的数据真的看起来很干净,那么您可以拆分"并获取结果数组中具有奇数索引的条目。

import pyspark.sql.functions as F

df2 = df.select(
    'id',
    F.posexplode(F.split('recs', '"')).alias('pos', 'like_id')
).filter('cast(pos % 2 as boolean)').drop('pos')

df2.show()
+---+-------+
| id|like_id|
+---+-------+
|ABC|     AB|
|XYZ|     XY|
|XYZ|     YZ|
|DEF|     DE|
|DEF|     EF|
|DEF|     FG|
+---+-------+

推荐阅读