如何匹配两个数据框的架构
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
【讨论】:
以上是关于如何匹配两个数据框的架构的主要内容,如果未能解决你的问题,请参考以下文章