【问题标题】:Spark Java: how to compare schemas when columns are not in the same order?Spark Java:当列的顺序不同时如何比较模式?
【发布时间】:2018-10-22 15:57:59
【问题描述】:

按照this question,我现在运行这段代码:

List<StructField> fields = new ArrayList<>();
fields.add(DataTypes.createStructField("A",DataTypes.LongType,true));
fields.add(DataTypes.createStructField("B",DataTypes.DoubleType,true));
StructType schema1 = DataTypes.createStructType(fields);
Dataset<Row> df1 = spark.sql("select 1 as A, 2.2 as B");
Dataset<Row> finalDf1 = spark.createDataFrame(df1.javaRDD(), schema1);

fields = new ArrayList<>();
fields.add(DataTypes.createStructField("B",DataTypes.DoubleType,true));
fields.add(DataTypes.createStructField("A",DataTypes.LongType,true));
StructType schema2 = DataTypes.createStructType(fields);
Dataset<Row> df2 = spark.sql("select 2.2 as B, 1 as A");
Dataset<Row> finalDf2 = spark.createDataFrame(df2.javaRDD(), schema2);

finalDf1.printSchema();
finalDf2.printSchema();
System.out.println(finalDf1.schema());
System.out.println(finalDf2.schema());
System.out.println(finalDf1.schema().equals(finalDf2.schema()));

这是输出:

root
 |-- A: long (nullable = true)
 |-- B: double (nullable = true)

root
 |-- B: double (nullable = true)
 |-- A: long (nullable = true)

StructType(StructField(A,LongType,true), StructField(B,DoubleType,true))
StructType(StructField(B,DoubleType,true), StructField(A,LongType,true))
false

虽然列的排列顺序不同,但这两个数据集的列和列类型完全相同。为了得到true,这里需要什么比较?

【问题讨论】:

  • 获取架构信息,按名称对列进行排序,然后按数据类型排序并进行比较。

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


【解决方案1】:

假设 order cols 不匹配并且相同的名称是相同的语义并且需要相同的列数。

一个使用 SCALA 的例子,你应该可以对 JAVA 进行裁剪:

import spark.implicits._
val df = sc.parallelize(Seq(
        ("A", "X", 2, 100), ("A", "X", 7, 100), ("B", "X", 10, 100),
        ("C", "X", 1, 100), ("D", "X", 50, 100), ("E", "X", 30, 100)
        )).toDF("c1", "c2", "Val1", "Val2")
val names = df.columns

val df2 = sc.parallelize(Seq(
       ("A", "X", 2, 1))).toDF("c1", "c2", "Val1", "Val2")
val names2 = df2.columns

names.sortWith(_ < _) sameElements names2.sortWith(_ < _)

返回真假,试验输入。

【讨论】:

    【解决方案2】:

    如果它们有不同的顺序,那么它们就不一样了。即使它们都具有相同的列数和相同的名称。如果您想查看两个架构是否具有相同的列名,则从两个 Dataframe 的列表中获取架构,然后编写代码来比较它们。请参阅下面的 java 示例

    public static void main(String[] args)
    {
    
        List<String> firstSchema =Arrays.asList(DataTypes.createStructType(ConfigConstants.firstSchemaFields).fieldNames());
        List<String> secondSchema = Arrays.asList(DataTypes.createStructType(ConfigConstants.secondSchemaFields).fieldNames());
    
    
        if(schemasHaveTheSameColumnNames(firstSchema,secondSchema))
        {
            System.out.println("Yes, schemas have the same column names");
        }else
        {
            System.out.println("No, schemas do not have the same column names");
        }
    }
    
    private static boolean schemasHaveTheSameColumnNames(List<String> firstSchema, List<String> secondSchema)
    {
        if(firstSchema.size() != secondSchema.size())
        {
            return false;
        }else 
        {
            for (String column : secondSchema)
            {
                if(!firstSchema.contains(column))
                    return false;
            }
        }
        return true;
    }
    

    【讨论】:

      【解决方案3】:

      按照前面的答案,似乎是比较StructFields(列和类型)而不仅仅是名称的最快方法如下:

      Set<StructField> set1 = new HashSet<>(Arrays.asList(schema1.fields()));
      Set<StructField> set2 = new HashSet<>(Arrays.asList(schema2.fields()));
      boolean result = set1.equals(set2);
      

      【讨论】:

      • return ds1.schema().fields().equals(ds2.schema().fields());
      猜你喜欢
      • 1970-01-01
      • 2019-01-05
      • 1970-01-01
      • 2022-10-13
      • 2016-12-25
      • 1970-01-01
      • 2016-12-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多