如何在循环中读取数据框列值并检查每列的数据类型

Posted

技术标签:

【中文标题】如何在循环中读取数据框列值并检查每列的数据类型【英文标题】: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|
+-----+-------+-----+-----------+

【问题讨论】:

【参考方案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("\\d1,2/\\d1,2/\\d1,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("\\d1,2/\\d1,2/\\d1,2$"):日期应具有此正则表达式中指定的格式。如果字符串匹配,rlike 返回 true,否则返回 false。 length(trim($"Place")) > 0: 当字符串为空时返回 null 否则返回 $"Place" 的值。

【讨论】:

以上是关于如何在循环中读取数据框列值并检查每列的数据类型的主要内容,如果未能解决你的问题,请参考以下文章

转换数据框列值并应用 SHA2 屏蔽逻辑

熊猫如何通过数据框列值获取行索引

如何检查同一数据框列中的重复值并通过根据频率删除行来应用 if 条件?

如何在 df.groupby 之后将数据框列值作为窗口大小传递?

Pandas / Numpy - 如何获取和比较每列与每列的计数并写入 csv?

如果数据框列值匹配字典键,检查不同的列是不是匹配字典值