web-dev-qa-db-ja.com

Spark RDDの要素に一意の連続した番号を割り当てる方法

(user, product, review)のデータセットがあり、mllibのALSアルゴリズムにフィードしたい。

アルゴリズムはユーザーと製品が数字である必要がありますが、私のものは文字列のユーザー名と文字列のSKUです。

今は、個別のユーザーとSKUを取得し、Sparkの外部でそれらに数値IDを割り当てています。

これを行うより良い方法があるかどうか疑問に思っていました。私が考えたアプローチの1つは、1〜nを本質的に列挙するカスタムRDDを作成し、2つのRDDでZipを呼び出すことです。

46
Dilum Ranatunga

Spark 1.から始めて、これを簡単に解決するために使用できる2つの方法があります。

  • RDD.zipWithIndexSeq.zipWithIndex、連続した(Long)番号を追加します。これは、各パーティションの要素を最初にカウントする必要があるため、入力は2回評価されます。これを使用する場合は、入力RDDをキャッシュします。
  • RDD.zipWithUniqueIdは、一意のLong IDも提供しますが、連続していることは保証されません。 (各パーティションの要素数が同じ場合にのみ連続します。)利点は、入力について何も知る必要がないため、二重評価が発生しないことです。
41
Daniel Darabos

同様の使用例では、文字列値をハッシュしました。 http://blog.cloudera.com/blog/2014/03/why-Apache-spark-is-a-crossover-hit-for-data-scientists/ を参照してください

def nnHash(tag: String) = tag.hashCode & 0x7FFFFF
var tagHashes = postIDTags.map(_._2).distinct.map(tag =>(nnHash(tag),tag))

あなたはすでにこのようなことをしているように聞こえますが、ハッシュは管理しやすいかもしれません。

Mateiは、ここで、RDDでzipWithIndexをエミュレートするアプローチを提案しました。これは、各パーティション内でグローバルに一意になるIDを割り当てることになります。 https://groups.google.com/forum/# !topic/spark-users/WxXvcn2gl1E

15
Sean Owen

別の簡単なオプションは、DataFramesを使用しており、一意性のみを懸念している場合、関数 MonotonicallyIncreasingID を使用することです。

import org.Apache.spark.sql.functions.monotonicallyIncreasingId 
val newDf = df.withColumn("uniqueIdColumn", monotonicallyIncreasingId)

編集:MonotonicallyIncreasingIDは廃止され、削除されました since Spark 2. ;現在はmonotonically_increasing_id

8
radek1st

すでに monotonically_increasing_id() を推奨しており、IntsではなくLongsを作成する問題に言及しています。

ただし、私の経験では(注意-Spark 1.6)-単一のエグゼキューターで使用する場合(前の1へのパーティション分割)、エグゼキュータープレフィックスは使用されず、数値を安全にキャストできます)明らかに、Integer.MAX_VALUE未満の行が必要です。

2
Eyal

monotonically_increasing_id()が表示されますが答えになりますが、残念ながらALSでは64ビットの数値を生成し、 ALSは32ビットのものを想定しています(deekについてはradek1stの回答を参照してください)。

私が見つけた解決策は、 zipWithIndex() を使用することです。これは、Darabosの回答に記載されています。実装方法は次のとおりです。

useridsと呼ばれる個別のユーザーを持つ単一列のDataFrameが既にある場合は、次のようにルックアップテーブル(LUT)を作成できます。

# PySpark code
user_als_id_LUT = sqlContext.createDataFrame(userids.rdd.map(lambda x: x[0]).zipWithIndex(), StructType([StructField("userid", StringType(), True),StructField("user_als_id", IntegerType(), True)]))

次のことができます。

  • このLUTを使用して、ALSに提供するALSフレンドリーな整数IDを取得します
  • ALS IDから元のIDに戻る必要がある場合、このLUTを使用して逆ルックアップを実行します

もちろん、アイテムにも同じことを行います。

2
xenocyon