动态循环所有列名称的数据集

时间:2019-04-05 13:22:02

标签: apache-spark apache-spark-sql apache-spark-dataset

我正在研究大约500个列名的项目,但是我需要在每个表名上应用coalesce函数。

df1模式

-id
-col1
...
-col500

df2模式

-id
-col1
...
-col500
Dataset<Row> newDS=  df1.join(df2, "id")
.select(
                df1.col("id"),
                functions.coalesce(df1.col("col1"),df2.col("col1")).as("col1"), 
                functions.coalesce(df1.col("col2"),df2.col("col2")).as("col2"),
...
functions.coalesce(df1.col("col500"),df2.col("col500")).as("col500"),
                )

        .show();

我尝试过的

 Dataset<Row> j1 =  df1.join(df2, "id");
Dataset<Row> gh1 = spark.emptyDataFrame();


    String[] f =  df1.columns();
     for(String h : f)
     {
         if(h == "id")
             gh1 = j1.select(df1.col("id"));
        else{
            gh1 = j1.select(functions.coalesce(df1.col(h),df2.col(h)).as(h));

        }


     }

     gh1.show();

3 个答案:

答案 0 :(得分:0)

如果我理解正确,您有两个具有相同架构的数据框,并且您希望将它们的500列2乘2合并,而不必编写所有内容。

可以通过为select提供一系列列来轻松实现。同样,由于select不接受列序列而是接受可变数量的列参数,因此您需要添加: _*以便让scala知道它需要将序列的所有元素视为单独的参数。

val cols = df1.columns.filter(_ != "id")
df1
    .join(df2, "id")
    .select(col("id") +: cols.map(n => coalesce(df1.col(n), df2.col(n)) as n) : _* )

答案 1 :(得分:0)

在Java中,您可以将值的数组传递给需要可变数量参数的方法,因此您可以像这样重写代码:

Column[] coalescedColumns = Stream.of(df1.columns())
             .map(name -> functions.coalesce(df1.col(name),df2.col(name)).as(name))
             .toArray(Column[]::new);

Dataset<Row> newDS = df1.join(df2, "id").select(coalescedColumns)

我没有排除id列,因为合并也可以在此列上按预期工作

答案 2 :(得分:0)

df1.columns将返回字符串数组,因此无法在其上调用流refer

Column[] coalescedColumns = 
                Stream.of(df1.columns())
               .map(name -> functions.coalesce(df1.col(name),df2.col(name)).as(name))
                 .toArray(Column[]::new);

        Dataset<Row> newDS = df1.as("a").join(df2.as("b")).where("a.id == b.id").select(coalescedColumns);