0

group_id、genderおよびheightの列を持つデータフレームがあります。spark udfを使用して既存の列から新しい列を作成し、グループを使用します。

group_idとheightはIntです。 性別は文字列です。

group_id| gender|height 
1  | F | 52 
1  | F | 53 
1  | F | 58 
1  | M | 55 
1  | M | 59 
2  | F | 50 
2  | M | 60 
2  | M | 61 
2  | M | 64 

私はGROUP_ID、性別及びheight_range 高さは何でも良い範囲でグループにたいのですが、私はここで簡単にするためにpredefined-例48-50、51-58,58-64など です5インチ増分を考慮して:50-54,55-59,60-64。

予想される出力:

group_id | gender | height_low | height_high | count 
    1  | F  | 50  | 54  | 2 
    1  | F  | 55  | 59  | 1 
    1  | M  | 55  | 59  | 2 
    2  | F  | 50  | 54  | 1 
    2  | M  | 60  | 64  | 3 

私は(とき)の合計を使用してみました。それは低い値と高い値を得るのにあまり役立たなかった。 私が考えることができる他の方法は、ハイブudfを2回使用し、height_lowをwhen節にさまざまな条件を設定し、別の時間にheight_highを設定することでした。 実行する必要がある同じチェックがあるため、これらの両方を同時に設定する方法があるかどうかを知りたいと思います。 何か助けていただければ幸いです。

答えて

1

あなたが必要ならば、height_lowheight_highを計算し、(他の列と一緒に)グループ化するためのキーとしてheight/5結果のfloor(切り捨て)を使用することができ:

import org.apache.spark.sql.functions._ 
import spark.implicits._ 

val result = df.groupBy($"group_id", $"gender", floor($"height"/5) * 5 as "height_low") 
    .count() 
    .withColumn("height_high", $"height_low" + 4) 

EDIT:私はappre

// For a set of ranges, given as an ordered list of range lower bounds: 
val rangeLowerBoundaries = List(50, 55, 60, 65) // ordered! 

// create UDF for finding the range, returns a tuple of (start, end), 
// uses 0 and MaxValue as edges of first and last range, respectively: 
val findMatchingRange = udf[(Int, Int), Int] { height => (
    rangeLowerBoundaries.filter(_ <= height).lastOption.getOrElse(0), 
    rangeLowerBoundaries.find(_ > height).getOrElse(Int.MaxValue) - 1 
)} 

// group by UDF and then select and rename tuple's elements: 
val result = df.groupBy($"group_id", $"gender", findMatchingRange($"height") as "range") 
    .count() 
    .select($"group_id", $"gender", $"range._1" as "height_low", $"range._2" as "height_high", $"count") 
    .show(false) 

result.show(false) 
// +--------+------+----------+-----------+-----+ 
// |group_id|gender|height_low|height_high|count| 
// +--------+------+----------+-----------+-----+ 
// |1  |F  |55  |59   |1 | 
// |2  |M  |60  |64   |3 | 
// |2  |F  |50  |54   |1 | 
// |1  |M  |55  |59   |2 | 
// |1  |F  |50  |54   |2 | 
// +--------+------+----------+-----------+-----+ 
+0

:範囲は必ずしも一定の大きさのないより一般的な場合は、実際の範囲を表すタプルを返すUDFを使用して解決することができますあなたの助けを捧げる。 申し訳ありませんが、私は明確ではありませんでした。しかし、これらの範囲は単なる例に過ぎません。 私は範囲を持つことができます。 48-50,51-53,54-64などと同様ですが、これらはすべて事前定義されており、ランダムに生成する必要はありません。 – dreddy

+0

これは一般的にどのように入力しますか?与えられた一連の範囲(サイズは異なるかもしれません)? –

+0

これは間違いない! :) 質問を編集しました。それを指摘してくれてありがとう。 – dreddy

関連する問題