Apache spark Spark:解析StringType列,并根据输入列中的值创建两个具有DoubleType和StringType的新列

Apache spark Spark:解析StringType列,并根据输入列中的值创建两个具有DoubleType和StringType的新列,apache-spark,apache-spark-sql,Apache Spark,Apache Spark Sql,如图所示,输入DF有一列“ColumnValues”和字符串值,需要创建两列“VALUE_NUMBER”和“VALUE_String”的输出数据框,这两列必须在解析“ColumnValues”字符串后包含值。如果是字符串值,则应转到“值字符串”列;如果是数字值,则应转到“值字符串”列。我有非常庞大的数据,需要高效地创建此输出。使用cast&当 将值转换为double如果能够成功转换双精度值,它将返回number否则null,然后在when函数中检查此null 检查下面的代码 解决方案1-在 sc


如图所示,输入DF有一列“ColumnValues”和字符串值,需要创建两列“VALUE_NUMBER”和“VALUE_String”的输出数据框,这两列必须在解析“ColumnValues”字符串后包含值。如果是字符串值,则应转到“值字符串”列;如果是数字值,则应转到“值字符串”列。我有非常庞大的数据,需要高效地创建此输出。

使用
cast
&

将值转换为
double
如果能够成功转换双精度值,它将返回
number
否则
null
,然后在
when
函数中检查此
null

检查下面的代码

解决方案1-在

scala> df.show(false)
+------------+
|columnvalues|
+------------+
|Maharashtra |
|23432.53    |
|Karnataka   |
|424244      |
|Goa         |
+------------+

scala> df
.withColumn("value_number",when(
        !$"columnvalues".cast("double").isNull,
        $"columnvalues"
    ).otherwise(0.0)
)
.withColumn("value_string",when(
        $"columnvalues".cast("double").isNull,
        $"columnvalues"
    ).otherwise("")
)
.show(false)
+------------+------------+------------+
|columnvalues|value_number|value_string|
+------------+------------+------------+
|Maharashtra |0.0         |Maharashtra |
|23432.53    |23432.53    |            |
|Karnataka   |0.0         |Karnataka   |
|424244      |424244      |            |
|Goa         |0.0         |Goa         |
+------------+------------+------------+

解决方案2-在
内部
选择时使用

df.select(
    $"columnvalues",
    when(!$"columnvalues".cast("double").isNull,$"columnvalues").otherwise(0.0).as("value_number"),
    when($"columnvalues".cast("double").isNull,$"columnvalues").otherwise("").as("value_string")
)
.show(false)

+------------+------------+------------+
|columnvalues|value_number|value_string|
+------------+------------+------------+
|Maharashtra |0.0         |Maharashtra |
|23432.53    |23432.53    |            |
|Karnataka   |0.0         |Karnataka   |
|424244      |424244      |            |
|Goa         |0.0         |Goa         |
+------------+------------+------------+


解决方案3-在
struct

val expr = when(
        !$"columnvalues".cast("double").isNull,
        struct(
            $"columnvalues".cast("double").as("value_number"),
            lit("").as("value_string")
        )
    ).otherwise(
        struct(
            lit(0.0).cast("double").as("value_number"),
            $"columnvalues".as("value_string")
        )
    ).as("value")

scala> df.select($"columnvalues",expr).select($"columnvalues",$"value.*").show(false)
+------------+------------+------------+
|columnvalues|value_number|value_string|
+------------+------------+------------+
|Maharashtra |0.0         |Maharashtra |
|23432.53    |23432.53    |            |
|Karnataka   |0.0         |Karnataka   |
|424244      |424244.0    |            |
|Goa         |0.0         |Goa         |
+------------+------------+------------+


我尝试了一个类似的例子

import pandas as pd
 cars = ['Honda Civic','Toyota Corolla','2000','30000','Ford Focus','Audi A4']
df = pd.DataFrame(cars, columns = ['Brand'])
df['brand_str'] = df.loc[~df['Brand'].astype(str).str.isdigit(),'Brand']
df['brand_int'] = df.loc[df['Brand'].str.isdigit(), 'Brand'] 
values = {'brand_str': '', 'brand_int': 0.0} 
df.fillna(value=values)
我希望这也适用于您的数据

  Brand        brand_str         brand_int
0   Honda Civic    Honda Civic          0.0
1   Toyota Corolla  Toyota Corolla      0.0
2   2000                               2000
3   30000                              30000
4   Ford Focus       Ford Focus        0.0
5   Audi A4          Audi A4           0.0

您可以通过以下简单的映射函数来实现

  • 加载数据帧
  • 尝试映射到双精度
  • 如果它是一个成功映射,则显式强制转换它,否则指定0.0
  • 如果双重强制转换失败,则将其强制转换为字符串或空字符串

  • Rajesh我加了一次溶液检查。。如果有帮助,请接受或投票:)
    import org.apache.spark.sql.SparkSession
    
    import scala.util.Try
    
    object MapToMultiColumns {
    
      def main(args: Array[String]): Unit = {
    
        val spark = SparkSession.builder.master("local[*]").getOrCreate;
    
        import spark.implicits._
    
        val df = List("Maharashtra","23432.53","Karnataka","424244","Goa").toDF("columnvalues")
    
        df.map(row => {
          val isDouble = Try(row.getString(0).toDouble).isSuccess
          val value_number : Double = if(isDouble) row.getString(0).toDouble else 0.0
          val value_string : String = if(!isDouble) row.getString(0) else ""
    
          (row.getString(0),value_number,value_string)
        }).toDF("columnvalues","value_number","value_string")
          .show()
    
      }
    
    }