Sparkを使った中央値・分位点の求め方
質問
の中央値を求めるにはどうしたらよいですか?
RDD
の中央値を求めることができますか?また
RDD
は約 70 万の要素であるため、収集して中央値を求めるには大きすぎます。
この質問と似ています。しかし、質問の答えはScalaを使用しており、私は知りません。
Apache Sparkで正確な中央値を計算するにはどうすればよいですか?
Scalaの回答の考え方を使って、Pythonで同様の回答を書こうとしています。
私は最初に
RDD
. 私は方法がわからない。私は
sortBy
(この RDD を与えられた
keyfunc
) と
sortByKey
(これをソートして
RDD
は、(キー、値)のペアで構成されていると仮定しています)メソッドです。どちらもキー・バリューを使うと思うのですが、私の
RDD
は整数の要素しか持っていません。
-
まず、私が考えていたのは
myrdd.sortBy(lambda x: x)
? -
次に、rddの長さを求めます(
rdd.count()
). - 最後に、rddの中心にある要素または2つの要素を見つけたい。この方法についても助けが必要です。
EDITです。
思いつきました。多分、私は私の
RDD
そして、キー=インデックスと値=要素です。そして、私は値でソートしようとすることができますか?私はそれが可能であるかどうかわからない。
sortByKey
メソッドしかないので、これが可能かどうかはわかりません。
どのように解決するのですか?
継続的な作業
SPARK-30569 - percentile_approx を呼び出す DSL 関数の追加
Spark 2.0+:
を使用することができます。
approxQuantile
を実装したメソッドです。
Greenwald-Khannaアルゴリズム
:
Python :
df.approxQuantile("x", [0.5], 0.25)
Scala :
df.stat.approxQuantile("x", Array(0.5), 0.25)
ここで、最後のパラメータは相対誤差である。数値が小さいほど、より正確な結果が得られ、より高価な計算が可能になります。
Spark 2.2以降( SPARK-14352 )からは、複数カラムでの推定をサポートしています。
df.approxQuantile(["x", "y", "z"], [0.5], 0.25)
と
df.approxQuantile(Array("x", "y", "z"), Array(0.5), 0.25)
基礎となるメソッドは、SQL集計(グローバルとグロッピングの両方)において
approx_percentile
関数を使うことができます。
> SELECT approx_percentile(10.0, array(0.5, 0.4, 0.1), 100);
[10.0,10.0,10.0]
> SELECT approx_percentile(10.0, 0.5, 100);
10.0
スパーク 2.0
Python
コメントで述べたように、それはすべての大騒ぎをする価値がない可能性が高いです。あなたのケースのようにデータが比較的小さい場合は、単にローカルで収集し、中央値を計算します。
import numpy as np
np.random.seed(323)
rdd = sc.parallelize(np.random.randint(1000000, size=700000))
%time np.median(rdd.collect())
np.array(rdd.collect()).nbytes
私の数年前のパソコンと5.5MB程度のメモリで0.01秒程度で表示されます。
もしデータがもっと大きければ、ソートが制限要因になるので、正確な値を得る代わりに、サンプリング、収集、ローカルでの計算を行う方が良いでしょう。しかし、もし本当にSparkを使いたいのであれば、このようなものがトリックになるでしょう(もし私が何かを台無しにしていなければ)。
from numpy import floor
import time
def quantile(rdd, p, sample=None, seed=None):
"""Compute a quantile of order p ∈ [0, 1]
:rdd a numeric rdd
:p quantile(between 0 and 1)
:sample fraction of and rdd to use. If not provided we use a whole dataset
:seed random number generator seed to be used with sample
"""
assert 0 <= p <= 1
assert sample is None or 0 < sample <= 1
seed = seed if seed is not None else time.time()
rdd = rdd if sample is None else rdd.sample(False, sample, seed)
rddSortedWithIndex = (rdd.
sortBy(lambda x: x).
zipWithIndex().
map(lambda (x, i): (i, x)).
cache())
n = rddSortedWithIndex.count()
h = (n - 1) * p
rddX, rddXPlusOne = (
rddSortedWithIndex.lookup(x)[0]
for x in int(floor(h)) + np.array([0L, 1L]))
return rddX + (h - floor(h)) * (rddXPlusOne - rddX)
そしていくつかのテスト。
np.median(rdd.collect()), quantile(rdd, 0.5)
## (500184.5, 500184.5)
np.percentile(rdd.collect(), 25), quantile(rdd, 0.25)
## (250506.75, 250506.75)
np.percentile(rdd.collect(), 75), quantile(rdd, 0.75)
(750069.25, 750069.25)
最後に中央値を定義します。
from functools import partial
median = partial(quantile, p=0.5)
ここまでは良いのですが、ネットワーク通信を行わないローカルモードでは4.66秒かかっています。おそらくこれを改善する方法があるはずですが、なぜ悩むのでしょうか?
言語に依存しない ( ハイブUDAF ):
もしあなたが
HiveContext
を使えば、HiveのUDAFも使えます。積分値で。
rdd.map(lambda x: (float(x), )).toDF(["x"]).registerTempTable("df")
sqlContext.sql("SELECT percentile_approx(x, 0.5) FROM df")
連続した値で
sqlContext.sql("SELECT percentile(x, 0.5) FROM df")
で
percentile_approx
では、使用するレコードの数を決定する追加の引数を渡すことができます。
関連
-
[解決済み] 関数デコレータを作成し、それらを連鎖させるには?
-
[解決済み] 辞書を値で並べ替えるにはどうしたらいいですか?
-
[解決済み] PandasでDataFrameの行を反復処理する方法
-
[解決済み] 割り当て後にリストが予期せず変更されました。その理由と防止策を教えてください。
-
[解決済み] リストに値が存在するかどうかを確認する最速の方法
-
[解決済み】整数の流れから実行中央値を求める
-
[解決済み] オブジェクトのリストに特定の属性値を持つオブジェクトが含まれているかどうかをチェックする
-
[解決済み] Pythonでマルチプロセッシングキューを使うには?
-
[解決済み] Pythonの文字列の前にあるbという接頭辞は何を意味するのですか?
-
[解決済み] Pythonでリストが空かどうかをチェックする方法は?重複
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] バブルソートの宿題
-
[解決済み] データフレームをソートした後にインデックスを更新する
-
[解決済み] ファブリック経由でデプロイユーザとしてvirtualenvを有効化する
-
[解決済み] Django で全てのリクエストヘッダを取得するにはどうすれば良いですか?
-
[解決済み] CSVデータを処理する際、1行目のデータを無視する方法を教えてください。
-
[解決済み] virtualenv の `--no-site-packages` オプションを元に戻す。
-
[解決済み] Pandasのデータフレーム内の文字列を'date'データ型に変換するにはどうしたらいいですか?
-
[解決済み] Django filter queryset __in for *every* item in list
-
[解決済み] 認証プラグイン 'caching_sha2_password' はサポートされていません。
-
クラス定義の外でメソッドを定義する?