【问题标题】:Compare and Highlight the differences of two dataframes using spark and java使用 spark 和 java 比较和突出两个数据帧的差异
【发布时间】:2021-11-24 04:09:06
【问题描述】:

我正在使用 sparkjava 来尝试比较两个数据帧。

将 csv 文件转换为数据帧后,我想准确突出显示两个数据帧之间的变化。

它们都有相同的列。

如您所见,以下数据帧唯一不正确的是第二个 df2 中的 emp_id 4。

Dataset<Row> df1 = spark.read().csv("/Users/dataframeOne.csv");
Dataset<Row> df1 = spark.read().csv("/Users/dataframeTwo.csv"); 
df1.unionAll(df2).except(df1.intersect(df2)).show(true);

Df1

+------+---------+--------+----------+-------+--------+
|emp_id| emp_city|emp_name| emp_phone|emp_sal|emp_site|
+------+---------+--------+----------+-------+--------+
|     3|  Chennai|  rahman|9848022330|  45000|SanRamon|
|     1|Hyderabad|     ram|9848022338|  50000|      SF|
|     2|Hyderabad|   robin|9848022339|  40000|      LA|
|     4|  sanjose|   romin|9848022331|  45123|SanRamon|
+------+---------+--------+----------+-------+--------+

Df2

+------+---------+--------+----------+-------+--------+
|emp_id| emp_city|emp_name| emp_phone|emp_sal|emp_site|
+------+---------+--------+----------+-------+--------+
|     3|  Chennai|  rahman|9848022330|  45000|SanRamon|
|     1|Hyderabad|     ram|9848022338|  50000|      SF|
|     2|Hyderabad|   robin|9848022339|  40000|      LA|
|     4|  sanjose|  romino|9848022331|  45123|SanRamon|
+------+---------+--------+----------+-------+--------+

区别

+------+--------+--------+----------+-------+--------+
|emp_id|emp_city|emp_name| emp_phone|emp_sal|emp_site|
+------+--------+--------+----------+-------+--------+
|     4| sanjose|  romino|9848022331|  45123|SanRamon|
+------+--------+--------+----------+-------+--------+

如何以黄色突出显示“Romino”,使用 JAVASPARK 的字段不正确?

【问题讨论】:

  • 您能否将示例数据添加为文本(而不是屏幕截图)。这样可以更轻松地重现您的问题。
  • 我认为你很接近。 df1.except(df2) 为您提供 df1 中的行,但不在 df2 中。因此,要了解两者之间的区别,请同时运行 df1.except(df2)df2.except(df1)
  • @m_vemuri 它打印出差异,但有没有办法突出差异,例如以黄色突出显示的“罗米诺”
  • @werner 希望它现在更容易阅读?
  • @JoeyOC 因为这都是程序化处理,所以突出显示不能轻易完成。它将需要某种用户界面/可能是 BI 工具。

标签: java dataframe apache-spark apache-spark-sql


【解决方案1】:

在 Spark 中突出显示某些内容取决于您的 GUI,因此作为第一步,我建议检测不同的值并将有关差异的信息作为附加列添加到数据框。

第 1 步:为两个数据框的所有列添加后缀,并将它们连接到主键 (emp_id):

import static org.apache.spark.sql.functions.*;

private static Dataset<Row> prefix(Dataset<Row> df, String prefix) {
    for(String col: df.columns()) df = df.withColumnRenamed(col, col + prefix);
    return df;
}

[...]
Dataset<Row> df1 = spark.read().option("header", "true").csv(...);
Dataset<Row> df2 = spark.read().option("header", "true").csv(...);

String[] columns = df1.columns();

Dataset<Row> joined = prefix(df1, "_1").join(prefix(df2, "_2"),
        col("emp_id_1").eqNullSafe(col("emp_id_2")), "full_outer");

第 2 步: 创建一个列对象列表,检查一个表中的值是否与另一个表不同。此列表稍后将用作map 的输入参数。

List<Column> diffs = new ArrayList<>();
for( String column: columns) {
    diffs.add(lit(column));
    diffs.add(when(col(column + "_1").eqNullSafe(col(column + "_2")), null)
            .otherwise(concat_ws("/", col(column + "_1"), col(column + "_2"))));
}

第 3 步:创建一个包含所有差异的地图的新列:

joined.withColumn("differences", map(diffs.toArray(new Column[]{})))
        .withColumn("differences", map_filter(col("differences"), (k, v) -> not(v.isNull())))
        .select("emp_id_1", "differences")
        .filter(size(col("differences")).gt(0))
        .show(false);

输出:

+--------+--------------------------+
|emp_id_1|differences               |
+--------+--------------------------+
|4       |{emp_name -> romin/romino}|
+--------+--------------------------+

【讨论】:

    猜你喜欢
    • 2020-06-07
    • 2012-09-12
    • 2018-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-30
    • 1970-01-01
    相关资源
    最近更新 更多