apache-spark - Spark : DataFrame Aggregation (Scala)

标签 apache-spark apache-spark-sql spark-dataframe

我有以下要求在 scala 中聚合 Spark 数据帧上的数据。 而且,我有两个数据集。

数据集 1 包含每个“t”类型的值 (val1, val2..),分布在几个不同的列上,例如 (t1,t2...)。

val data1 = Seq(
    ("1","111",200,"221",100,"331",1000),
    ("2","112",400,"222",500,"332",1000),
    ("3","113",600,"223",1000,"333",1000)
).toDF("id1","t1","val1","t2","val2","t3","val3")

data1.show()

+---+---+----+---+----+---+----+
|id1| t1|val1| t2|val2| t3|val3|
+---+---+----+---+----+---+----+
|  1|111| 200|221| 100|331|1000|
|  2|112| 400|222| 500|332|1000|
|  3|113| 600|223|1000|333|1000|
+---+---+----+---+----+---+----+    

数据集 2 表示同一事物,每个“t”类型都有一个单独的行。

val data2 = Seq(("1","111",200),("1","221",100),("1","331",1000),
  ("2","112",400),("2","222",500),("2","332",1000),
  ("3","113",600),("3","223",1000), ("3","333",1000)
).toDF("id*","t*","val*")

data2.show()    

+---+---+----+
|id*| t*|val*|
+---+---+----+
|  1|111| 200|
|  1|221| 100|
|  1|331|1000|
|  2|112| 400|
|  2|222| 500|
|  2|332|1000|
|  3|113| 600|
|  3|223|1000|
|  3|333|1000|
+---+---+----+      

现在,我需要对 groupBY(id,t,t*) 字段进行分组,并将 sum(val) 和 sum(val*) 的余额打印为单独的记录。 并且两者的余额应该相等。

My output should look like below:
+---+---+--------+---+---------+
|id1| t |sum(val)| t*|sum(val*)|
+---+---+--------+---+---------+
|  1|111|     200|111|      200|
|  1|221|     100|221|      100|
|  1|331|    1000|331|     1000|
|  2|112|     400|112|      400|
|  2|222|     500|222|      500|
|  2|332|    1000|332|     1000|
|  3|113|     600|113|      600|
|  3|223|    1000|223|     1000|
|  3|333|    1000|333|     1000|
+---+---+--------+---+---------+

我正在考虑将数据集 1 分解为每个“t”类型的多个记录,然后与数据集 2 连接。 但是,您能否建议我一个更好的方法,如果数据集变大也不会影响性能?

最佳答案

最简单的解决方案是进行子选择,然后合并数据集:

val ts = Seq(1, 2, 3)
val dfs = ts.map (t => data1.select("t" + t as "t", "v" + t as "v"))
val unioned = dfs.drop(1).foldLeft(dfs(0))((l, r) => l.union(r))

val ds = unioned.join(df2, 't === col("t*")
here aggregation

你也可以尝试使用 explode 数组:

val df1 = data1.withColumn("colList", array('t1, 't2, 't3))
               .withColumn("t", explode(colList))
               .select('t, 'id1 as "id")

val ds = df2.withColumn("val", 
          when('t === 't1, 'val1)
          .when('t === 't2, 'val2)
          .when('t === 't3, 'val3)
          .otherwise(0))

最后一步是将此数据集与 data2 连接起来:

ds.join(data2, 't === col("t*"))
  .groupBy("t", "t*")
  .agg(first("id1") as "id1", sum(val), sum("val*"))

关于apache-spark - Spark : DataFrame Aggregation (Scala),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48416586/

相关文章:

python发送csv数据到spark streaming

scala - 具有特征的 Spark 2.0 数据集编码器

apache-spark - 为什么Apache Spark会读取嵌套结构中不必要的Parquet列?

apache-spark - 选择 map 键作为 Spark 数据框中的列

java - 在 Spark 中将数据集应用为广播

sql - 使用 Scala 中的数据帧在 Spark 1.30 中保存为文本

python - PySpark 新列,从整数列表中选择值

python - Pyspark 基于具有列表或集合的多个条件的其他列创建新列

hadoop - Hive的unbase64()函数的结果在Hive表中是正确的,但在输出文件中变为错误

mysql - 与 MySQL (Apache Spark) 建立永久连接