在 spark sql 中将字符串类型转换为数组类型

Posted

技术标签:

【中文标题】在 spark sql 中将字符串类型转换为数组类型【英文标题】:Convert string type to array type in spark sql 【发布时间】:2020-01-10 14:02:03 【问题描述】:

我在 Databricks 中的 Spark SQL 中有表,并且我有一个作为字符串的列。我将新列转换为数组数据类型,但它们仍然是一个字符串。数据类型是表架构中的数组类型

作为字符串的列

Data1 
[2461][2639][2639][7700][7700][3953]

转换为数组

Data_New
["[2461][2639][2639][7700][7700][3953]"]

字符串到数组的转换

df_new = df.withColumn("Data_New", array(df["Data1"])) 

然后写成 parquet 并在 databricks 中用作 spark sql 表

当我使用 array_contains 函数搜索字符串时,我得到的结果为 false

select *
from table_name
where array_contains(Data_New,"[2461]")

当我搜索所有字符串时,查询将结果变为真

请建议我是否可以将这些字符串分隔为数组,并可以使用array_contains 函数找到任何数组。

【问题讨论】:

【参考方案1】:

只需从字符串中删除前括号和尾括号,然后用][ 分割即可得到字符串数组:

df = df.withColumn("Data_New", split(expr("rtrim(']', ltrim('[', Data1))"), "\\]\\["))
df.show(truncate=False)

+------------------------------------+------------------------------------+
|Data1                               |Data_New                            |
+------------------------------------+------------------------------------+
|[2461][2639][2639][7700][7700][3953]|[2461, 2639, 2639, 7700, 7700, 3953]|
+------------------------------------+------------------------------------+

现在像这样使用array_contains

df.createOrReplaceTempView("table_name")

sql_query = "select * from table_name where array_contains(Data_New,'2461')"
spark.sql(sql_query).show(truncate=False)

【讨论】:

【参考方案2】:

其实这不是一个数组,这是一个完整的字符串,所以你需要一个正则表达式或类似的

expr = "[2461]"
df_new.filter(df_new["Data_New"].rlike(expr))

【讨论】:

【参考方案3】:

导入

from pyspark.sql import functions as sf, types as st

创建表

a = [["[2461][2639][2639][7700][7700][3953]"], [None]]
sdf = sc.parallelize(a).toDF(["col1"])
sdf.show()
+--------------------+
|                col1|
+--------------------+
|[2461][2639][2639...|
|                null|
+--------------------+

转换类型

def spliter(x):
    if x is not None:
        return x[1:-1].split("][")
    else:
        return None
udf = sf.udf(spliter, st.ArrayType(st.StringType()))
sdf.withColumn("array_col1", udf("col1")).withColumn("check", sf.array_contains("array_col1", "2461")).show()
+--------------------+--------------------+-----+
|                col1|          array_col1|check|
+--------------------+--------------------+-----+
|[2461][2639][2639...|[2461, 2639, 2639...| true|
|                null|                null| null|
+--------------------+--------------------+-----+

【讨论】:

看起来这会起作用,但是当尝试将数据帧写入镶木地板文件时出现错误。文件“”,第 2 行,在 TypeError: 'NoneType' object is not subscriptable 请建议 您的数据框中是否缺少像 nan 这样的数据?如果是这种情况,我需要修改 UDF 以过滤掉缺失值 是的,数据框中缺少值。 我更新了答案,请注意,如果你的df很大,python udf会影响你的性能,所以blackbishop的答案在性能方面更好

以上是关于在 spark sql 中将字符串类型转换为数组类型的主要内容,如果未能解决你的问题,请参考以下文章

如何在 spark sql 连接条件中将字符串数据类型转换为日期:to_date 不起作用并且转换抛出错误

在 Spark SQL 中将 long 类型的列转换为 calendarinterval 类型

在 Spark SQL 中将结构转换为映射

Scala - 如何在 Spark SQL 查询中将日期字符串转换为时间戳?

如何在Spark sql中将列转换为Int

如何在pyspark中将字符串列转换为ArrayType