python - 将 Pyspark 数据框中的字典拆分为单独的列

标签 python apache-spark dictionary dataframe pyspark

我有一个数据框(在 Pyspark 中),其中一个行值作为字典:

df.show()

看起来像:

+----+---+-----------------------------+
|name|age|info                         |
+----+---+-----------------------------+
|rob |26 |{color: red, car: volkswagen}|
|evan|25 |{color: blue, car: mazda}    |
+----+---+-----------------------------+

根据评论给出更多:

df.printSchema()

类型是字符串

root
 |-- name: string (nullable = true)
 |-- age: string (nullable = true)
 |-- dict: string (nullable = true)

是否可以从字典中获取键(颜色和汽车)并将它们设为数据框中的列,并将值作为这些列的行?

预期结果:

+----+---+-----------------------------+
|name|age|color |car                   |
+----+---+-----------------------------+
|rob |26 |red   |volkswagen            |
|evan|25 |blue  |mazda                 |
+----+---+-----------------------------+

我不知道我必须使用 df.withColumn() 并以某种方式遍历字典来选择每个字典,然后从中创建一列?到目前为止,我已经尝试找到一些答案,但大多数都使用 Pandas,而不是 Spark,所以我不确定是否可以应用相同的逻辑。

最佳答案

你的字符串:

"{color: red, car: volkswagen}"
"{color: blue, car: mazda}"

不是Python友好的格式。它们无法使用 json.loads 进行解析,也不能使用 ast.literal_eval 进行评估。

但是,如果您提前知道 key 并且可以假设字符串始终采用这种格式,那么您应该能够使用 pyspark.sql.functions.regexp_extract :

例如:

from pyspark.sql.functions import regexp_extract

df.withColumn("color", regexp_extract("info", "(?<=color: )\w+(?=(,|}))", 0))\
    .withColumn("car", regexp_extract("info", "(?<=car: )\w+(?=(,|}))", 0))\
    .show(truncate=False)
#+----+---+-----------------------------+-----+----------+
#|name|age|info                         |color|car       |
#+----+---+-----------------------------+-----+----------+
#|rob |26 |{color: red, car: volkswagen}|red  |volkswagen|
#|evan|25 |{color: blue, car: mazda}    |blue |mazda     |
#+----+---+-----------------------------+-----+----------+

模式是:

  • (?<=color: ) :文字字符串 "color: " 的正向后查找
  • \w+ :一个或多个单词字符
  • (?=(,|})) :对原义逗号或右大括号进行积极的前瞻。
<小时/>

以下是如何将其推广到两个以上的键,并处理字符串中不存在该键的情况。

from pyspark.sql.functions import regexp_extract, when, col
from functools import reduce

keys = ["color", "car", "year"]
pat = "(?<=%s: )\w+(?=(,|}))"

df = reduce(
    lambda df, c: df.withColumn(
        c,
        when(
            col("info").rlike(pat%c),
            regexp_extract("info", pat%c, 0)
        )
    ),
    keys,
    df
)

df.drop("info").show(truncate=False)
#+----+---+-----+----------+----+
#|name|age|color|car       |year|
#+----+---+-----+----------+----+
#|rob |26 |red  |volkswagen|null|
#|evan|25 |blue |mazda     |null|
#+----+---+-----+----------+----+

在本例中,我们使用 pyspark.sql.functions.whenpyspark.sql.Column.rlike在我们尝试提取匹配之前测试字符串是否包含模式。

<小时/>

如果您事先不知道 key ,则必须编写自己的解析器或尝试修改上游数据。

关于python - 将 Pyspark 数据框中的字典拆分为单独的列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53072138/

相关文章:

python - 我可以将值列表设置为字典中的键列表吗?

python - 如何动态地将value设置为复杂的json内容,接收key(或key路径)和value作为参数

apache-spark - 列变换后的 Pyspark 随机森林特征重要性映射

Python:带有 2 个样本的二维 Kolmogorov-Smirnov

python反斜杠正则表达式的乐趣

python - 从 excel 到 mysql 的格式字符串参数不足

machine-learning - 在 Spark 中使用 Silhouette 聚类

macos - Hadoop 3.3.0 : RPC response has invalid length

python 访问字典有两个键,只使用一个键

python - 概率解析器的内存使用