有没有一种方法可以在不使用正则表达式的情况下将字符串转换[R55, B66]
回来array<string>
?
设置
在此输出中,我们看到codes
列是 StringType。StringType 是输出所必需的,但这使得用户使用输出更加困难。
样本输入数据
input_data = """[{
"id":"1234",
"code":"R55"
},{
"id":"123",
"code":"B66"
}]"""
input_df = spark.read.json(sc.parallelize([input_data]))
如何创建表格
output_df = input_df.groupBy('id').agg(F.array_agg('code').alias('codes'))
output_df = output_df.withColumn('codes', F.col('codes').cast("string"))
ID | 代码 |
---|---|
1234 | [R55,B66] |
# schema
root
|-- id: string (nullable = true)
|-- codes: string (nullable = false)
担忧
regexp 似乎是将string
列转换回的唯一选项array<string>
什么有效
df = output_df.withColumn('codes_array', F.expr(r"regexp_extract_all(codes, '(\\w+)', 1)"))
ID | 代码 | 代码数组 |
---|---|---|
67550581 | [IS0386085, IS0385475] | [IS0386085, IS0385475] |
# schema
root
|-- id: string (nullable = true)
|-- codes: string (nullable = false)
|-- codes_array: array (nullable = false)
| |-- element: string (containsNull = true)
什么不起作用
示例 1 - 返回 NULL
schema = T.ArrayType(T.StringType())
df = output_df.withColumn('codes_array', F.from_json(F.col('codes'), schema))\
ID | 代码 | 代码数组 |
---|---|---|
1234 | [R55,B66] | 无效的 |
# schema
root
|-- ServiceActivityID: string (nullable = true)
|-- correction_codes: string (nullable = false)
|-- codes_array: array (nullable = false)
| |-- element: string (containsNull = true)
示例 2 - 返回错误消息
schema = T.ArrayType(T.StringType())
df = output_df.withColumn('codes_array', F.from_json(F.col('codes'), schema, {'mode': 'FAILFAST'}))
原因:org.apache.spark.sql.catalyst.util.BadRecordException:com.fasterxml.jackson.core.JsonParseException:无法识别的令牌“R55”:预期为(JSON 字符串、数字(或“NaN”/“INF”/“+INF”)、数组、对象或令牌“null”、“true”或“false”)
问题
有没有办法不使用正则表达式来读codes
回该列?array<string>
或者有没有办法让codes
列写入与非正则表达式函数一起使用的 StringType 格式(如from_json
)?
(通过我目前的方法,似乎 spark 很乐意在一个方向上转换类型,但并没有将它们设置为能够轻松转换回来的格式。考虑到 StringType 约束,是否有更好的方法可以对该表进行读/写?)
直接使用 生成的字符串
cast('string')
并不是标准的JSON字符串,可以使用to_json
函数生成标准JSON字符串,然后使用from_json
。