web-dev-qa-db-ja.com

PySpark DataFrames-パンダに変換せずに列挙する方法は?

非常に大きなpyspark.sql.dataframe.DataFrameという名前のdfがあります。レコードを列挙する何らかの方法が必要です。つまり、特定のインデックスを持つレコードにアクセスできます。 (またはインデックス範囲を持つレコードのグループを選択します)

パンダでは、私はちょうど作ることができました

indexes=[2,3,6,7] 
df[indexes]

ここで私は似たようなものが欲しい、(そしてデータフレームをパンダに変換せずに)

一番近いのは:

  • 元のデータフレーム内のすべてのオブジェクトを列挙する方法:

    indexes=np.arange(df.count())
    df_indexed=df.withColumn('index', indexes)
    
    • Where()関数を使用して必要な値を検索します。

質問:

  1. なぜ機能しないのか、どのように機能させるのですか?データフレームに行を追加する方法は?
  2. のようなものを作るために後で動作しますか:

     indexes=[2,3,6,7] 
     df1.where("index in indexes").collect()
    
  3. それに対処するより速くて簡単な方法はありますか?

14
Maria Koroliuk

衝突しないことが保証されているが、.over(partitionBy())を必要としない数値範囲が必要な場合は、monotonicallyIncreasingId()を使用できます。

from pyspark.sql.functions import monotonicallyIncreasingId
df.select(monotonicallyIncreasingId().alias("rowId"),"*")

ただし、値は特に「ニート」ではないことに注意してください。各パーティションには値の範囲が与えられ、出力は連続しません。例えば。 0, 1, 2, 8589934592, 8589934593, 8589934594

これはSpark 2015年4月28日にここに追加されました: https://github.com/Apache/spark/commit/d94cd1a733d5715792e6c4eac87f0d5c81aebbe2

11
Joe Harris

確かに、インデックス付け用の配列、実際に選択した配列を追加できます。Scalaでは、最初にインデックス付け配列を作成する必要があります。

val index_array=(1 to df.count.toInt).toArray

index_array: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

これで、DFにこの列を追加できます。まず、そのために、DFを開いて配列として取得し、index_arrayでZipしてから、新しい配列をRDDに変換し直す必要があります。最後のステップはDFとして取得するには:

final_df = sc.parallelize((df.collect.map(
    x=>(x(0),x(1))) Zip index_array).map(
    x=>(x._1._1.toString,x._1._2.toString,x._2))).
    toDF("column_name")

その後、インデックス作成がより明確になります。

1
Mahdi Ghelichi