spark:解析stringtype列,并根据输入列中的值创建两个具有doubletype和stringtype的新列

hs1ihplo  于 2021-05-29  发布在  Spark
关注(0)|答案(3)|浏览(402)

输入\输出\图像
如图所示,input df有一列“columnvalues”和字符串值,需要创建两列“value\u number”和“value\u string”的输出数据框,解析“columnvalues”字符串后必须包含值。如果是字符串值,则应转到“值\字符串”列;如果是数字值,则应转到“值\数字”列。我有非常巨大的数据,需要有效地创建这个输出。

mefy6pfw

mefy6pfw1#

您可以通过以下简单的Map函数来实现,
加载Dataframe
尝试Map到双精度
如果它是一个成功Map,则显式地将其转换为else赋值0.0
如果双重强制转换失败,则将其强制转换为字符串或空字符串

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()

  }

}
shyt4zoc

shyt4zoc2#

使用 cast & when 把价值投给 double 如果它能够成功地转换double值,它将返回 number 其他 null 那你看看这个 null 内部 when 功能。
检查以下代码。
解决方案1-使用 withColumn & when ```
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-使用 `when` 内部 `select` ```
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-使用 when & 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 |
+------------+------------+------------+

mo49yndu

mo49yndu3#

我试过一个类似的例子

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

相关问题