在spark scala中对多个数据帧执行左外连接

时间:2018-02-02 22:57:49

标签: scala apache-spark spark-dataframe

我是Spark的新手。我尝试使用scala实现以下用例。

List<Integer>

最终输出框应该是

public static List<Integer> indexOf(String text, char index) {
    return IntStream.range(0, text.length())
                    .filter(i -> s.charAt(i) == index)
                    .boxed()
                    .collect(Collectors.toList());
}

帧数不限于3,它可以是小于100的任何数字。所以我用于打印每个数据帧的每个数据。

有人可以帮助我如何创建最终数据框,我可以使用N个数据帧以上述格式输出。

感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

您可以使用"wb"以迭代方式将数据与外部联接

合并
foldLeft

但如果你真的想到

  

它可以是任何小于100的数字

然后这是不切实际的。 import org.apache.spark.sql.Row import org.apache.spark.sql.functions._ val df1 = Seq((1, "a"), (2, "a"), (3, "a")).toDF("Col A", "Col B") val df2 = Seq((1, "b"), (2, "b")).toDF("Col A", "Col B") val df3 = Seq((2, "c"), (3, "c")).toDF("Col A", "Col B") val dfs = Seq(df2, df3) val bs = (0 to dfs.size).map(i => s"Col B $i") dfs.foldLeft(df1)( (acc, df) => acc.join(df, Seq("Col A"), "fullouter") ).toDF("Col A" +: bs: _*).select($"Col A", array(bs map col: _*)).map { case Row(a: Int, bs: Seq[_]) => // Drop nulls and concat (a, bs.filter(_ != null).map(_.toString).mkString(",")) }.toDF("Col A", "Col B").show // +-----+-----+ // |Col A|Col B| // +-----+-----+ // | 1| a,b| // | 3| a,c| // | 2|a,b,c| // +-----+-----+ 是Spark中最昂贵的操作,即使有了所有优化器改进,它也无法正常工作。

答案 1 :(得分:0)

我今天看到了这个问题。我建议你用python来解决它。它比scala更容易编写。他们是:

from pyspark.sql import SQLContext

from pyspark.sql.functions import concat_ws

d1=sc.parallelize([(1, "a"), (2, "a"), (3,"a")]).toDF().toDF("Col_A","Col_B")

d2=sc.parallelize([(1, "b"), (2, "b")]).toDF().toDF("Col_A", "Col_B")

d3=sc.parallelize([(2, "c"), (3, "c")]).toDF().toDF("Col_A", "Col_B")

d4=d1.join(d2,'Col_A','left').join(d3,'Col_A','left').select(d1.Col_A.alias("col A"),concat_ws(',',d1.Col_B,d2.Col_B,d3.Col_B).alias("col B"))

df4.show()

+-----+-----+

|col A|col B|

+-----+-----+

|    1
|  a,b|

|    2
|a,b,c|

|    3
|  a,c|

+-----+-----+

你看到了结果!