【问题标题】:Convert string type to array type in spark sql在 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 函数找到任何数组。

【问题讨论】:

    标签: apache-spark pyspark apache-spark-sql


    【解决方案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的答案在性能方面更好
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-13
        • 1970-01-01
        • 2019-02-09
        • 2021-05-10
        • 2021-12-14
        相关资源
        最近更新 更多