私はpandasおよびsparkデータフレームを使用しています。データフレームは常に非常に大きく(> 20 GB)、標準spark =関数はこれらのサイズには不十分です。現在、pandasデータフレームをsparkデータフレームに次のように変換しています:
dataframe = spark.createDataFrame(pandas_dataframe)
sparkを使用すると、データフレームをhdfsに書き込むのが非常に簡単であるため、この変換を行います。
dataframe.write.parquet(output_uri, mode="overwrite", compression="snappy")
しかし、2 GBを超えるデータフレームの変換は失敗しています。 sparkデータフレームをpandasに変換すると、pyarrowを使用できます。
// temporary write spark dataframe to hdfs
dataframe.write.parquet(path, mode="overwrite", compression="snappy")
// open hdfs connection using pyarrow (pa)
hdfs = pa.hdfs.connect("default", 0)
// read parquet (pyarrow.parquet (pq))
parquet = pq.ParquetDataset(path_hdfs, filesystem=hdfs)
table = parquet.read(nthreads=4)
// transform table to pandas
pandas = table.to_pandas(nthreads=4)
// delete temp files
hdfs.delete(path, recursive=True)
これはspark to pandasからの高速な会話であり、2 GBを超えるデータフレームでも機能します。他の方法はまだ見つかりませんでした。 pandasデータフレームをpyarrowの助けを借りてsparkに変換することを意味します。問題は、私が実際に= pandas hdfsへのデータフレーム。
私のpandasバージョン:0.19.0
Pyarrowを使用してpandasデータフレームをsparkに変換することを意味します。
pyarrow.Table.fromPandas
は、探している関数です。
Table.from_pandas(type cls, df, bool timestamps_to_ms=False, Schema schema=None, bool preserve_index=True) Convert pandas.DataFrame to an Arrow Table
import pyarrow as pa
pdf = ... # type: pandas.core.frame.DataFrame
adf = pa.Table.from_pandas(pdf) # type: pyarrow.lib.Table
結果は、Sparkを介してデータを渡すことなく、Parquet/HDFSに直接書き込むことができます。
import pyarrow.parquet as pq
fs = pa.hdfs.connect()
with fs.open(path, "wb") as fw
pq.write_table(adf, fw)
も参照してください
pyarrow
のドキュメント 。スパークノート:
さらに、Spark 2.3(現在のマスター)ArrowがcreateDataFrame
で直接サポートされているため( SPARK-20791-Apache Arrowを使用してSpark createDataFrame from Pandas.DataFrame を改善) 。それは SparkContext.defaultParallelism
を使用してチャンクの数を計算する なので、個々のバッチのサイズを簡単に制御できます。
最後に、defaultParallelism
を使用して、標準の_convert_from_pandas
を使用して生成されるパーティションの数を制御し、スライスのサイズをより扱いやすいものに効果的に縮小できます。
残念ながら、これらが 現在のメモリの問題 を解決する可能性は低いです。どちらもparallelize
に依存しているため、すべてのデータをドライバーノードのメモリに格納します。 Arrowへの切り替えまたは構成の調整は、プロセスまたはアドレスブロックサイズの制限をスピードアップするだけです。
実際には、ローカルSpark DataFrame
を入力として使用している限り、ここでPandasに切り替える理由はありません。このシナリオで最も深刻なボトルネックは、ドライバーのネットワークI/Oであり、データの配信では対応できません。
もう1つの方法は、pandasデータフレームをsparkデータフレーム(pysparkを使用)に)変換し、saveコマンドでhdfsに保存することです。
df = pd.read_csv("data/as/foo.csv")
df[['Col1', 'Col2']] = df[['Col2', 'Col2']].astype(str)
sc = SparkContext(conf=conf)
sqlCtx = SQLContext(sc)
sdf = sqlCtx.createDataFrame(df)
ここでastype
は、列のタイプをobject
からstring
に変更します。これは、sparkが理解できなかったpandas type object
であるため、他の方法で発生した例外からあなたを救います。しかし、これらの列が本当にタイプであることを確認してくださいストリング。
次に、dfをhdfsに保存します。
sdf.write.csv('mycsv.csv')
から https://issues.Apache.org/jira/browse/SPARK-6235
2GBより大きいR data.frameの並列化のサポート
解決されました。
から https://pandas.pydata.org/pandas-docs/stable/r_interface.html
データフレームをRオブジェクトに変換する
pandas dataframeをR data.frameに変換できます
したがって、おそらく変換pandas-> R-> Spark-> hdfs?