Pyspark 将结构数组转换为字符串
Posted
技术标签:
【中文标题】Pyspark 将结构数组转换为字符串【英文标题】:Pyspark converting an array of struct into string 【发布时间】:2019-08-06 17:52:25 【问题描述】:我在 Pyspark 中有以下数据框
+----+-------+-----+
|name|subject|score|
+----+-------+-----+
| Tom| math| 90|
| Tom|physics| 70|
| Amy| math| 95|
+----+-------+-----+
我使用了来自pyspark.sql.functions
的collect_list
和struct
函数
df.groupBy('name').agg(collect_list(struct('subject', 'score')).alias('score_list'))
获取以下数据帧
+----+--------------------+
|name| score_list|
+----+--------------------+
| Tom|[[math, 90], [phy...|
| Amy| [[math, 95]]|
+----+--------------------+
我的问题是如何将最后一列 score_list
转换为字符串并将其转储到 csv 文件中,如下所示
Tom (math, 90) | (physics, 70)
Amy (math, 95)
感谢任何帮助,谢谢。
更新:Here 是一个类似的问题,但并不完全相同,因为它直接从 string
转到另一个 string
。就我而言,我想先将string
转移到collect_list<struct>
,最后将这个collect_list<struct>
字符串化。
【问题讨论】:
使用concat_ws
- 寻找骗子。
Concatenating string by rows in pyspark、combine text from multiple rows in pyspark 或 Combine multiple rows into a single row 的可能重复项。
你的 spark 版本是多少?
@jxc 我用的是 spark 2.4.3
【参考方案1】:
根据您的更新和评论,对于 Spark 2.4.0+,这是使用 Spark SQL 内置函数对结构数组进行字符串化的一种方法:transform 和 array_join:
>>> df.printSchema()
root
|-- name: string (nullable = true)
|-- score_list: array (nullable = true)
| |-- element: struct (containsNull = true)
| | |-- subject: string (nullable = true)
| | |-- score: integer (nullable = true)
>>> df.show(2,0)
+----+---------------------------+
|name|score_list |
+----+---------------------------+
|Tom |[[math, 90], [physics, 70]]|
|Amy |[[math, 95]] |
+----+---------------------------+
>>> df1.selectExpr(
"name"
, """
array_join(
transform(score_list, x -> concat('(', x.subject, ', ', x.score, ')'))
, ' | '
) AS score_list
"""
).show(2,0)
+----+--------------------------+
|name|score_list |
+----+--------------------------+
|Tom |(math, 90) | (physics, 70)|
|Amy |(math, 95) |
+----+--------------------------+
地点:
-
使用 transform() 将结构数组转换为字符串数组。对于每个数组元素(结构
x
),我们使用concat('(', x.subject, ', ', x.score, ')')
将其转换为字符串。
使用 array_join() 将所有数组元素(StringType)与 |
连接起来,这将返回最终字符串
【讨论】:
【参考方案2】:我链接的重复项并不能完全回答您的问题,因为您正在组合多个列。不过,您可以很容易地修改解决方案以适应您想要的输出。
只需将struct
替换为concat_ws
。还可以使用concat
添加左括号和右括号以获得所需的输出。
from pyspark.sql.functions import concat, concat_ws, lit
df = df.groupBy('name')\
.agg(
concat_ws(
" | ",
collect_list(
concat(lit("("), concat_ws(", ", 'subject', 'score'), lit(")"))
)
).alias('score_list')
)
df.show(truncate=False)
#+----+--------------------------+
#|name|score_list |
#+----+--------------------------+
#|Tom |(math, 90) | (physics, 70)|
#|Amy |(math, 95) |
#+----+--------------------------+
请注意,由于逗号出现在score_list
列中,如果您使用默认参数,当您写入csv
时,该值将被引用。
例如:
df.coalesce(1).write.csv("test.csv")
将产生以下输出文件:
Tom,"(math, 90) | (physics, 70)"
Amy,"(math, 95)"
【讨论】:
以上是关于Pyspark 将结构数组转换为字符串的主要内容,如果未能解决你的问题,请参考以下文章