2017-10-20 10 views
1

spark/scalaにはまったく新しいです。私は、列方向にArray [Double]を集約する簡単な方法があるのだろうかと思います。次に例を示します。配列要素を集約する

c1 c2 c3 
------------------------- 
1  1 [1.0, 1.0, 3.4] 
1  2 [1.0, 0,0, 4.3] 
2  1 [0.0, 0.0, 0.0] 
2  3 [1.2, 1.1, 1.1] 

次に、集約時に、私は次のようになり、テーブルで終わるだろう:今UDAFを見て

c1 c3prime 
------------- 
1  [2.0, 1.0, 7.7] 
2  [1.2, 1.1, 1.1] 

が、私はまったくコーディングする必要がある場合は不思議でしたか?

ありがとうございました。 c3の配列値は、同じサイズのものであると仮定すると、

答えて

0

、あなたは以下のようなUDFによって列要素単位を加算することができます

val df = Seq(
    (1, 1, Seq(1.0, 1.0, 3.4)), 
    (1, 2, Seq(1.0, 0.0, 4.3)), 
    (2, 1, Seq(0.0, 0.0, 0.0)), 
    (2, 3, Seq(1.2, 1.1, 1.1)) 
).toDF("c1", "c2", "c3") 

def elementSum = udf(
    (a: Seq[Seq[Double]]) => { 
    val zeroSeq = Seq.fill[Double](a(0).size)(0.0) 
    a.foldLeft(zeroSeq)(
     (a, x) => (a zip x).map{ case (u, v) => u + v } 
    ) 
    } 
) 

val df2 = df.groupBy("c1").agg(
    elementSum(collect_list("c3")).as("c3prime") 
) 

df2.show(truncate=false) 
// +---+-----------------------------+ 
// |c1 |c3prime      | 
// +---+-----------------------------+ 
// |1 |[2.0, 1.0, 7.699999999999999]| 
// |2 |[1.2, 1.1, 1.1]    | 
// +---+-----------------------------+ 
+0

こんにちは、これは素晴らしいです。どうもありがとうございました。考案されたサンプルは、あなたが指定した通り、期待どおりに動作します。 – Kirby

0

は、ここではUDFのないものです。 Sparkのウィンドウ機能を利用しています。それは、複数のgroupBy

df.show 

// +---+---+---------------+ 
// | c1| c2|    c3| 
// +---+---+---------------+ 
// | 1| 1|[1.0, 1.0, 3.4]| 
// | 1| 2|[1.0, 0.0, 4.3]| 
// | 2| 1|[0.0, 0.0, 0.0]| 
// | 2| 2|[1.2, 1.1, 1.1]| 
// +---+---+---------------+ 

import org.apache.spark.sql.expressions.Window 

val window = Window.partitionBy($"c1", $"c2").orderBy($"c1", $"c2") 

df.withColumn("c3", explode($"c3")) 
    .withColumn("rn", row_number() over window) 
    .groupBy($"c1", $"rn").agg(sum($"c3").as("c3")) 
    .orderBy($"c1", $"rn") 
    .groupBy($"c1") 
    .agg(collect_list($"c3").as("c3prime")).show 

// +---+--------------------+ 
// | c1|    c3prime| 
// +---+--------------------+ 
// | 1|[2.0, 1.0, 7.6999...| 
// | 2|  [1.2, 1.1, 1.1]| 
// +---+--------------------+ 
+0

ありがとうございます。これも興味深い展望です。私はそれが役立つかどうかを見るためにこれと遊びます。 – Kirby

0

を伴うため、それがどのように効率的にわからないあなたはdataframe所望の最終を取得するなどgroupByaggsumarrayaliasas)など、いくつかのinbuilt functionsを組み合わせることができます。

import org.apache.spark.sql.functions._ 
df.groupBy("c1") 
    .agg(sum($"c3"(0)).as("c3_1"), sum($"c3"(1)).as("c3_2"), sum($"c3"(2)).as("c3_3")) 
    .select($"c1", array("c3_1","c3_2","c3_3").as("c3prime")) 

私は答えが役に立ちそうです。

関連する問題