如何匹配两个数据框的架构

Posted

技术标签:

【中文标题】如何匹配两个数据框的架构【英文标题】:How to match Schema of two Data Frames 【发布时间】:2019-06-13 11:04:50 【问题描述】:

我在表中保存了默认列名,我想将保存在表中的列名与我将在 CSV 文件中接收到的列名相匹配。

以下代码的结果是:

如果文件具有与表中存储的相同的列名以进行匹配,则执行一些处理,否则退出并抛出不匹配架构的电子邮件。

这是我的代码:

val expectedschemadf = spark.sql(s"""SELECT columnname FROM  table""").columns
val receivedschemadf = spark.table(vendorfile.toString).columns

if(expectedschemadf.size == receivedschemadf.size)

  breakable for(i<-0 to expectedschemadf.size-1 by 1)
  
    if (!(receivedschemadf contains expectedschemadf(i)))
    
      print("fail")
      break
    

  
  

else(print("fail"))

我想要的结果:

我想将上面的 for 循环自动化到一些预定义的函数中。

【问题讨论】:

【参考方案1】:

以下是检查两个数据框架构的示例代码

scala> val df1 = Seq((1,"a", 1.5)).toDF
df1: org.apache.spark.sql.DataFrame = [_1: int, _2: string ... 1 more field]

scala> df1.printSchema
root
 |-- _1: integer (nullable = false)
 |-- _2: string (nullable = true)
 |-- _3: double (nullable = false)

scala> val df2 = Seq((100,"x", 1231)).toDF
df2: org.apache.spark.sql.DataFrame = [_1: int, _2: string ... 1 more field]

scala> df2.printSchema
root
 |-- _1: integer (nullable = false)
 |-- _2: string (nullable = true)
 |-- _3: integer (nullable = false)


scala> df1.schema == df2.schema
res7: Boolean = false

scala> val df3 = Seq((100,"x", 123.1)).toDF
df3: org.apache.spark.sql.DataFrame = [_1: int, _2: string ... 1 more field]

scala> df3.printSchema
root
 |-- _1: integer (nullable = false)
 |-- _2: string (nullable = true)
 |-- _3: double (nullable = false)


scala> df1.schema == df3.schema
res9: Boolean = true

【讨论】:

rjshkrmara:感谢您分享您的帮助。基本上我已经完成了你提到的模式检查部分,但现在我想比较列名而不是数据类型。 like:我已将列名存储在 hive 的表中,然后需要将这些名称与文件头进行比较。如果文件头包含与表中存储的列相同的名称,则继续,否则中断工作。 只要在 DF 中获取输入文件的 dtypes。如果您采用元组的第一个变体,它应该给您列名列表,第二个应该有类型。您可以将您的表整体放入另一个序列并匹配序列【参考方案2】:

我没有在环境中运行此代码,但这通常是如何将列的名称放入 seq 和 Seq.equals 应该返回 true,如果序列的顺序和成员相同,如果有则返回 false差异。

val tableSeq = Seq("name","address","zip") // simulating a seq that you can retrive from your table 
val inputdf = spark.read.json("path") // reading some external data into dataframe
val columnListUnzipped = inputdf.dtypes.unzip // unzip will give tupple of column name and type
val columnList= columnListUnzipped._1 // get all column names as a seq
val isEqual= tableSeq.euqals(columnList) // compare 2 sequences with using equal as provided by Scala

【讨论】:

谢谢 Aaron:我已经更新了我的问题,我想自动化我的代码 不确定您还需要什么.. 上面的代码应该可以完成您想要完成的工作【参考方案3】:

这就是我完成任务的方式。

val expectedCol = dfMetaDataFileTracker.select("COLUMNNAME").collect().map(_.getString(0)).sorted.toList.map(_.toUpperCase()) 
val receivedCol = dfVendorFile.columns.sorted.toList.map(_.toUpperCase())
  if ((expectedCol.length == receivedCol.length) && (expectedCol.equals(receivedCol))) 
  
    println("file schema matched with the expected schema!")
    break
  
  else 
    println("file schema does not matched with the expected schema!")
    break        
  

【讨论】:

以上是关于如何匹配两个数据框的架构的主要内容,如果未能解决你的问题,请参考以下文章

熊猫数据框:在进行涉及两个数据框的算术运算时如何在多个索引级别上进行匹配

给定主键,比较两个数据框的其他列,垂直输出diff列

如何根据共同日期在单个数据框中对齐两个数据框的数据[重复]

不同数据框的模糊匹配列

如何使用 C# 设置列表框的高度以匹配其中的元素数量?

将数据框的新列分配给与其他数据框匹配的值[重复]