【问题标题】:How to Read dataframe column value in loop and check datatype of each column如何在循环中读取数据框列值并检查每列的数据类型
【发布时间】:2019-07-01 09:32:35
【问题描述】:

我需要一些帮助来理解“scala”中的迭代。我有一个数据框,它具有不同类型的数据'(Int,String,Date,Long)'。我想循环读取每一行数据。如果列数据与数据类型不匹配,则数据类型正确。然后我想用 null 更新列的值。

我已经厌倦了读取每个列的值并检查相应的数据类型,例如“ID 列是:整数类型,AirName:字符串类型,位置:字符串类型,TakeoffDate:日期”类型。我的输入数据集是:

+-----+-------+-----+-----------+
|   ID|AirName|Place|TakeoffDate|
|    1|  Delta|  Aus|    1/11/18|
|    2|  Delta|     |    10/5/19|
|Three|   null|  New| 15/10/2018|
|    4| JetAir|  Aus|    11/6/15|
+-----+-------+-----+-----------+

这里的三是字符串类型,但我们将 ID 声明为 Int 类型。所以我想用空替换三。循环中的其他列类似。

我从文件中读取数据并创建了一个数据框。现在我想用各自的数据类型检查每一行和每一列。如果数据类型不匹配,我想用 null 替换该列。

但这对我不起作用。

val myFile = sc.textFile("/FileStore/tables/Airline__2_-14f6c.txt")

import org.apache.spark.sql.types._
case class Test(ID:Int,AirName:String,Place:String,TakeoffDate:String)
val df= myFile.map(x => x.split(",") ).map( x=> Test(x(0).toInt,x(1),x(2),x(3)) ).toDF()

def isInt(in: Integer): Option[Int] = {
    try {
        Some(Integer.parseInt(in))
    } catch {
        case e: NumberFormatException => None
    }
}

rows.map{
     case(ID) => if (isInt(ID).isEmpty (ID,ErrorCodes.NOT_INT)) 
  {
    println("yes")
  }
  else ((Int)ID, None)
  {
    println("no")
  }
}

Expected Output
+-----+-------+-----+-----------+
|   ID|AirName|Place|TakeoffDate|
|    1|  Delta|  Aus|    1/11/18|
|    2|  Delta| null|    10/5/19|
|null |   null|  New|     null  |
|    4| JetAir|  Aus|    11/6/15|
+-----+-------+-----+-----------+

【问题讨论】:

    标签: scala apache-spark


    【解决方案1】:

    我建议使用提供更丰富功能的数据帧/数据集 API,而不是使用 RDD API:

    import org.apache.spark.sql.functions.{trim, length, when}
    
    val df = Seq(
      ("1", "Delta", "Aus", "1/11/18"),
      ("2", "Delta", null, "10/5/19"),
      ("Three", null, "New", "15/10/2018"),
      ("4", "JetAir", "Aus", "11/6/15"))
    .toDF("ID", "AirName","Place", "TakeoffDate")
    
    df.withColumn("ID", $"ID".cast("int"))
    .withColumn("TakeoffDate", 
                when(
                  $"TakeoffDate".rlike("\\d{1,2}/\\d{1,2}/\\d{1,2}$"), $"TakeoffDate")
                .otherwise(null)
               )
    .withColumn("Place", 
                when(
                    length(trim($"Place")) > 0, $"Place")
                .otherwise(null))
    .show(false)
    

    输出:

    +----+-------+-----+-----------+
    |ID  |AirName|Place|TakeoffDate|
    +----+-------+-----+-----------+
    |1   |Delta  |Aus  |1/11/18    |
    |2   |Delta  |null |10/5/19    |
    |null|null   |New  |null       |
    |4   |JetAir |Aus  |11/6/15    |
    +----+-------+-----+-----------+
    

    选角

    • $"ID".cast("int"):您将任何字符串转换为 int。如果无法转换,则默认情况下强制转换将返回 null。
    • $"TakeoffDate".rlike("\\d{1,2}/\\d{1,2}/\\d{1,2}$"):日期应具有此正则表达式中指定的格式。如果字符串匹配,rlike 返回 true,否则返回 false。
    • length(trim($"Place")) > 0: 当字符串为空时返回 null 否则返回 $"Place" 的值。

    【讨论】:

      猜你喜欢
      • 2023-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-18
      • 1970-01-01
      • 2020-01-21
      相关资源
      最近更新 更多