首页 > 解决方案 > 从 pyspark 数据框列创建结构数组

问题描述

我正在寻找有关 Pyspark 数据框的帮助,其中包含如下列:

价值
id1:xxx1xxx
id2:666x666
id1:xxx4xxx||id2:555x555||id1:xxx5xxx

我想要创建的是一个附加列,其中这些值位于结构数组中。这样做的目的是与另一个数据框的值匹配。我希望这个问题在任何方面都有意义。

已经能够将数据框列转换为以下内容:

["id1:xxx7xxx", "id2:777l777", "id1:999xx99"]

关于如何将其转换为结构化数组的任何建议?

谢谢

标签: arrayspyspark

解决方案


上面的代码产生的输出类似于您指定的输出,但使用映射作为需要动态的名称。请注意,如果您只需要事先知道的少数有限数量的 ID(id1、id2、id3),那么我可能会采用稍微不同的方法。另请注意,输出与您指定的略有不同,因为如果只有 1 个 ID,您将有一个包含 1 个项目的列表,但我不确定是否可以按照您指定的方式使用它,因为您会要求 2 个不同的“类型”作为值(如果 > 1 val 则列出,如果只有一个值则为字符串)无论如何都会导致问题。

我本可以用更少的步骤完成此操作,但想向您展示思考过程并引导您完成它。

from pyspark.sql import functions as F

df = spark.createDataFrame([("id1:xxx7xxx", ), ("id2:777l777", ), ("id1:xxx4xxx||id2:555x555||id1:xxx5xxx",  )], ["Value"])

# split the string based on the || and then explode 
# the reason i am keeping the Value is because we will want to use it to group by to get the split_val back to their original rows - if there are other columns you can use for the group by, you do not need to keep it 
df = df.select("Value", F.explode(F.split(F.col("Value"), "\|\|")).alias('split_val'))

df = df.withColumn("id_num", F.split(F.col("split_val"), ":").getItem(0)) \
.withColumn("id_val", F.split(F.col("split_val"), ":").getItem(1))

df = df.groupBy(["Value", "id_num"]).agg(F.collect_list("id_val").alias("id_val_list")) \
.withColumn("idMap", F.create_map(F.col("id_num"), F.col("id_val_list")))

# now group by original value to get this back in one row per Value
df = df.groupBy(["Value"]).agg(F.collect_list("idMap").alias("ValueList"))

# If you don't want Value anymore, you can just select Value List and rename it to Value
df = df.select(F.col("ValueList").alias("Value"))

推荐阅读