Java Spark:比较两个数据集
我正在做一个spark工作,从两个不同的位置读取拼花地板文件中的数据。这些拼花地板文件由两个不同的源生成,但源相同。 我想比较这两个拼花地板文件中的数据集,看看是否有任何列值被删除 有没有办法比较两个数据集并显示不匹配的列 数据集parquetFile=spark 阅读 .parquetfile//file1.parquet;Java Spark:比较两个数据集,java,apache-spark,Java,Apache Spark,我正在做一个spark工作,从两个不同的位置读取拼花地板文件中的数据。这些拼花地板文件由两个不同的源生成,但源相同。 我想比较这两个拼花地板文件中的数据集,看看是否有任何列值被删除 有没有办法比较两个数据集并显示不匹配的列 数据集parquetFile=spark 阅读 .parquetfile//file1.parquet; 在非常高的级别上,您可以尝试以下操作: 将数据从两个位置加载到单独的数据帧df1和df2中。 将id字段上的df1和df2连接到df3 为df3编写映射函数,在其中比较
在非常高的级别上,您可以尝试以下操作: 将数据从两个位置加载到单独的数据帧df1和df2中。 将id字段上的df1和df2连接到df3 为df3编写映射函数,在其中比较联接的左侧和右侧。 map函数的返回结果可能类似于包含行id和不匹配的列名/值对列表的元组。 在UI中存储结果或预览。
我的解决方案是Scala,但你也可以用Java来解决,因为想法是一样的 当比较spark中的两个数据集/数据帧时,我可以想到多种方法,你可以进行df。除了两次,即A-B和B-A,然后连接两个结果数据帧,但这是一个大量的洗牌,如果列数增加,则会占用大量存储下面的方法是最简单的,只需要一次洗牌,即使有数千个专栏和数百万条记录,它也能发挥魅力:
case class Person(name: String, age: Long)
import spark.implicits._
def main(args: Array[String]): Unit = {
val source = Seq(Person("Andy", 32), Person("Farhan", 26), Person("John", 23)).toDS().toDF
val target = Seq(Person("Andy", 32), Person("Farhan", 25), Person("John", 23)).toDS().toDF
compareTwoDatasets(spark, source, target, "name").show(10, false)
}
def compareTwoDatasets(spark: SparkSession, sourceDS: Dataset[Row], targetDS: Dataset[Row], uniqueColumnName: String) = {
val source = sourceDS.map(sourceRow => (sourceRow.getAs(uniqueColumnName).toString, sourceRow.mkString("|"))).toDF(uniqueColumnName, "source_record")
val target = targetDS.map(targetRow => (targetRow.getAs(uniqueColumnName).toString, targetRow.mkString("|"))).toDF(uniqueColumnName, "target_record")
val columns = sourceDS.columns
source
.join(target, uniqueColumnName)
.where($"source_record" =!= $"target_record")
.flatMap { row =>
val sourceArray = row.getAs[String]("source_record").split("\\|", -1)
val targetArray = row.getAs[String]("target_record").split("\\|", -1)
val commonValue = row.getAs[String](uniqueColumnName)
List(columns, sourceArray, targetArray)
.transpose
.filter(x => x(1) != x(2))
.map((commonValue, _))
}.toDF(uniqueColumnName, "mismatch_column_source_target")
}
输出:
+------+-----------------------------+
|name |mismatch_column_source_target|
+------+-----------------------------+
|Farhan|[age, 26, 25] |
+------+-----------------------------+
第二列中的值将是不匹配的列名、源值及其对应的目标值。在我看来,最好回答这个问题,但使用DF和SCALA以及更通用的方法,这样也可以工作 例如,模拟输入:
case class Person(personid: Int, personname: String, cityid: Int)
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.functions._
val df1 = Seq(
Person(0, "AgataZ", 0),
Person(1, "Iweta", 0),
Person(2, "Patryk", 2),
Person(9999, "Maria", 2),
Person(5, "John", 2),
Person(6, "Patsy", 2),
Person(7, "Gloria", 222),
Person(3333, "Maksym", 0)).toDF
val df2 = Seq(
Person(0, "Agata", 0),
Person(1, "Iweta", 0),
Person(2, "Patryk", 2),
Person(5, "John", 2),
Person(6, "Patsy", 333),
Person(7, "Gloria", 2),
Person(4444, "Hans", 3)).toDF
val joined = df1.join(df2, df1("personid") === df2("personid"), "outer")
val newNames = Seq("personId1", "personName1", "personCity1", "personId2", "personName2", "personCity2")
val df_Renamed = joined.toDF(newNames: _*)
// Some deliberate variation shown in approach for learning
val df_temp = df_Renamed.filter($"personCity1" =!= $"personCity2" || $"personName1" =!= $"personName2" || $"personName1".isNull || $"personName2".isNull || $"personCity1".isNull || $"personCity2".isNull).select($"personId1", $"personName1".alias("Name"), $"personCity1", $"personId2", $"personName2".alias("Name2"), $"personCity2"). withColumn("PersonID", when($"personId1".isNotNull, $"personId1").otherwise($"personId2"))
val df_final = df_temp.withColumn("nameChange ?", when($"Name".isNull or $"Name2".isNull or $"Name" =!= $"Name2", "Yes").otherwise("No")).withColumn("cityChange ?", when($"personCity1".isNull or $"personCity2".isNull or $"personCity1" =!= $"personCity2", "Yes").otherwise("No")).drop("PersonId1").drop("PersonId2")
df_final.show()
gives:
+------+-----------+------+-----------+--------+------------+------------+
| Name|personCity1| Name2|personCity2|PersonID|nameChange ?|cityChange ?|
+------+-----------+------+-----------+--------+------------+------------+
| Patsy| 2| Patsy| 333| 6| No| Yes|
|Maksym| 0| null| null| 3333| Yes| Yes|
| null| null| Hans| 3| 4444| Yes| Yes|
|Gloria| 222|Gloria| 2| 7| No| Yes|
| Maria| 2| null| null| 9999| Yes| Yes|
|AgataZ| 0| Agata| 0| 0| Yes| No|
+------+-----------+------+-----------+--------+------------+------------+
接受答案可能是个好主意?Project有一个数据集比较模块,可以帮助您。可以用作库。这不是很通用,我宁愿使用