web-dev-qa-db-ja.com

Spark dataframe with CSV as partitions)を書き込みます

sparkのデータフレームをHDFSの場所に書き込もうとしています。partitionBy表記を追加すると、Sparkがパーティションを作成することを期待しています(Parquet形式で書き込むのと同様) )の形式のフォルダ

partition_column_name=partition_value

(つまり、partition_date=2016-05-03)。そのために、次のコマンドを実行しました。

(df.write
    .partitionBy('partition_date')
    .mode('overwrite')
    .format("com.databricks.spark.csv")
    .save('/tmp/af_organic'))

しかし、パーティションフォルダーは作成されていませんでした。spark DFがそれらのフォルダーを自動的に作成するために何をすべきでしょうか?

おかげで、

10
Lior Baber

Spark 2.0.0 +

組み込みのcsv形式は、箱から出してパーティショニングをサポートしているため、次のように簡単に使用できます。

df.write.partitionBy('partition_date').mode(mode).format("csv").save(path)

追加のパッケージを含めずに

スパーク<2.0.0

現時点(v1.4.0)spark-csvpartitionByをサポートしていません( databricks/spark-csv#12 を参照)。ただし、組み込みのソースを調整して、目的を達成できます。

2つの異なるアプローチを試すことができます。データが比較的単純で(複雑な文字列がなく、文字をエスケープする必要がない)、多かれ少なかれ次のようになっているとします。

df = sc.parallelize([
    ("foo", 1, 2.0, 4.0), ("bar", -1, 3.5, -0.1)
]).toDF(["k", "x1", "x2", "x3"])

書き込む値を手動で準備できます。

from pyspark.sql.functions import col, concat_ws

key = col("k")
values = concat_ws(",", *[col(x) for x in df.columns[1:]])

kvs = df.select(key, values)

textソースを使用して書き込む

kvs.write.partitionBy("k").text("/tmp/foo")

df_foo = (sqlContext.read.format("com.databricks.spark.csv")
    .options(inferSchema="true")
    .load("/tmp/foo/k=foo"))

df_foo.printSchema()
## root
## |-- C0: integer (nullable = true)
## |-- C1: double (nullable = true)
## |-- C2: double (nullable = true)

より複雑なケースでは、適切なCSVパーサーを使用して、UDFを使用するか、RDDを介してマッピングすることにより、同様の方法で値を前処理することができますが、コストが大幅に高くなります。

CSV形式が難しい要件ではない場合は、そのままでpartitionByをサポートするJSONライターを使用することもできます。

df.write.partitionBy("k").json("/tmp/bar")

読み取り時のパーティション検出と同様に。

23
zero323