【问题标题】:Convert Array form (as String) to Column in Pyspark将数组形式(作为字符串)转换为 Pyspark 中的列
【发布时间】:2018-07-30 15:50:19
【问题描述】:

我有一个带有这种形式的 df:

+---------------------------------------+
|ID|ESTRUC_COMP                         |
+---------------------------------------+
|4A|{'AP': '201', 'BQ': '2'}            |
|8B| {'AP': '501', 'BQ': '1', 'IN': '5'}|
+---------------------------------------+

我需要这样的东西:

+------------------------------------------------+
|ID|ESTRUC_COMP                        |AP |BQ|IN|
+------------------------------------------------+
|4A|{'AP': '201', 'BQ': '2'}           |201|2 |  |
|8B|{'AP': '501', 'BQ': '1', 'IN': '5'}|501|1 |5 |
+------------------------------------------------+

但是,ESTRUC_COMP 是一个字符串。

root
 |-- ID: string (nullable = true)
 |-- ESTRUC_COMP: string (nullable = true)

如何执行此转换?提前谢谢你。

鲍里斯

【问题讨论】:

  • 也许可以将列转换为结构类型,然后在stackoverflow.com/questions/47874037/…中应用解决方案
  • 什么版本的火花?
  • 嗨@pault,1.6.1
  • 不明白...我在列中没有字典,我有一个字符串列。我需要将其转换为 dict 或尝试使用 String

标签: arrays pyspark pivot


【解决方案1】:

由于您使用的是 Spark 1.6,因此您不能使用 pyspark.sql.functions.from_json() - 您将不得不使用 udf

这个问题与PySpark “explode” dict in column 非常相似,但我认为这不是一个骗局,原因有两个:

  1. 您的字符串列不是有效的 JSON(因为单引号)

  2. 您希望键成为列

尽管如此,第一步基本上是按照链接帖子中的相同步骤,对parse() 函数进行小幅调整,该函数将单引号替换为双引号:

from pyspark.sql.functions import udf, explode, first
from pyspark.sql.types import *
import json

def parse(s):
    try:
        return json.loads(s.replace("'", '"'))
    except json.JSONDecodeError:
        pass

parse_udf = udf(parse, MapType(StringType(), StringType()))

现在你可以解析字符串并调用pyspark.sql.functions.explode()

df.select("ID",  explode(parse_udf("ESTRUC_COMP"))).show()
#+---+---+-----+
#| ID|key|value|
#+---+---+-----+
#| 4A| BQ|    2|
#| 4A| AP|  201|
#| 8B| IN|    5|
#| 8B| BQ|    1|
#| 8B| AP|  501|
#+---+---+-----+

最后,pivot() 将键作为列。您可以使用first() 作为聚合函数,因为我们知道每个ID 的键值关系是一对一的。

df.select("*", explode(parse_udf("ESTRUC_COMP")))\
    .groupBy("ID","ESTRUC_COMP").pivot("key").agg(first("value")).show(truncate=False)
#+---+-----------------------------------+---+---+----+
#|ID |ESTRUC_COMP                        |AP |BQ |IN  |
#+---+-----------------------------------+---+---+----+
#|4A |{'AP': '201', 'BQ': '2'}           |201|2  |null|
#|8B |{'AP': '501', 'BQ': '1', 'IN': '5'}|501|1  |5   |
#+---+-----------------------------------+---+---+----+

当然,由于我将udf 定义为返回MapType(StringType(), StringType()),因此您生成的所有列都将是字符串。您可以cast them 或相应地修改udf

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-07
    相关资源
    最近更新 更多