【问题标题】:Casting string to ArrayType(DoubleType) pyspark dataframe将字符串转换为 ArrayType(DoubleType) pyspark 数据帧
【发布时间】:2020-10-02 03:44:41
【问题描述】:

我在 Spark 中有一个具有以下架构的数据框: 架构:

StructType(List(StructField(id,StringType,true),
StructField(daily_id,StringType,true),
StructField(activity,StringType,true)))

列活动是一个字符串,示例内容:

{1.33,0.567,1.897,0,0.78}

我需要将列 Activity 转换为 ArrayType(DoubleType)

为了完成这项工作,我运行了以下命令:

df = df.withColumn("activity",split(col("activity"),",\s*").cast(ArrayType(DoubleType())))

dataframe 的新 schema 相应改变:

StructType(List(StructField(id,StringType,true),
StructField(daily_id,StringType,true),
StructField(activity,ArrayType(DoubleType,true),true)))

但是,数据现在看起来像这样: [NULL,0.567,1.897,0,NULL]

它将字符串数组的第一个和最后一个元素更改为 NULL。我不明白为什么 Spark 对数据框这样做。

请帮忙看看是什么问题?

非常感谢

【问题讨论】:

标签: python arrays dataframe apache-spark casting


【解决方案1】:

因为

以下代码不会替换 { & }

df.withColumn("activity",F.split(F.col("activity"),",\s*")).show(truncate=False)
+-------------------------------+
|activity                       |
+-------------------------------+
|[{1.33, 0.567, 1.897, 0, 0.78}]|
+-------------------------------+

当您尝试将这些 {1.330.78} 字符串值转换为 DoubleType 时,您将得到 null 作为输出。

df.withColumn("activity",F.split(F.col("activity"),",\s*").cast(ArrayType(DoubleType()))).show(truncate=False)
+----------------------+
|activity              |
+----------------------+
|[, 0.567, 1.897, 0.0,]|
+----------------------+

改变这个

df.withColumn("activity",split(col("activity"),",\s*").cast(ArrayType(DoubleType())))

from pyspark.sql import functions as F
from pyspark.sql.types import ArrayType
from pyspark.sql.types import DoubleType

df.select(F.split(F.regexp_replace(F.col("activity"),"[{ }]",""),",").cast("array<double>").alias("activity"))

【讨论】:

    【解决方案2】:

    发生这种情况是因为您的第一个和最后一个字母是括号本身,因此将其转换为 null

    
    testdf.withColumn('activity',f.split(f.col('activity').substr(f.lit(2),f.length(f.col('activity'))-2),',').cast(t.ArrayType(t.DoubleType()))).show(2, False)
    

    【讨论】:

      【解决方案3】:

      试试这个-

         val df = Seq("{1.33,0.567,1.897,0,0.78}").toDF("activity")
          df.show(false)
          df.printSchema()
          /**
            * +-------------------------+
            * |activity                 |
            * +-------------------------+
            * |{1.33,0.567,1.897,0,0.78}|
            * +-------------------------+
            *
            * root
            * |-- activity: string (nullable = true)
            */
          val processedDF = df.withColumn("activity",
            split(regexp_replace($"activity", "[^0-9.,]", ""), ",").cast("array<double>"))
          processedDF.show(false)
          processedDF.printSchema()
      
          /**
            * +-------------------------------+
            * |activity                       |
            * +-------------------------------+
            * |[1.33, 0.567, 1.897, 0.0, 0.78]|
            * +-------------------------------+
            *
            * root
            * |-- activity: array (nullable = true)
            * |    |-- element: double (containsNull = true)
            */
      

      【讨论】:

        【解决方案4】:

        使用 Spark SQL 的简单方法(无正则表达式):

        df2=(df1
             .withColumn('col1',expr("""
             transform(
             split(
             substring(activity,2,length(activity)-2),','),
             x->DOUBLE(x))
             """))
            )
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-02-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-10-21
          • 1970-01-01
          相关资源
          最近更新 更多