2016-02-16 14 views
8

古典的なETLジョブを実行するためにPySparkを使用しています(データセットを読み込み、処理して保存します)、 "仮想"列でパーティション化されたファイル/ ; 「バーチャル」とは、ISO 8601でエンコードされた日付を含む文字列の列Timestampを持っており、年/月/日でパーティション化したいということです。実際には、DataFrameにYear、MonthまたはDayのいずれかの列はありません。私は、これらの列を派生させることができるこのタイムスタンプを持っていますが、私はこれらの列の1つをシリアル化するために私のresultat項目を望んでいません。以下のようになります。ディスクにデータフレームを保存起因するスパーク: "仮想"列でパーティション化されたDataFrameを保存する

ファイル構造:

/ 
    year=2016/ 
     month=01/ 
      day=01/ 
       part-****.gz 

/Pysparkスパークで私が欲しいものを行う方法はありますか?

答えて

15

パーティション化に使用される列は、シリアル化されたデータ自体には含まれません。たとえば、あなたはこのようにDataFrameを作成する場合:

df = sc.parallelize([ 
    (1, "foo", 2.0, "2016-02-16"), 
    (2, "bar", 3.0, "2016-02-16") 
]).toDF(["id", "x", "y", "date"]) 

と、次のようにそれを書く:

import tempfile 
from pyspark.sql.functions import col, dayofmonth, month, year 
outdir = tempfile.mktemp() 

dt = col("date").cast("date") 
fname = [(year, "year"), (month, "month"), (dayofmonth, "day")] 
exprs = [col("*")] + [f(dt).alias(name) for f, name in fname] 

(df 
    .select(*exprs) 
    .write 
    .partitionBy(*(name for _, name in fname)) 
    .format("json") 
    .save(outdir)) 

個々のファイルは、パーティション列が含まれていません。

import os 

(sqlContext.read 
    .json(os.path.join(outdir, "year=2016/month=2/day=16/")) 
    .printSchema()) 

## root 
## |-- date: string (nullable = true) 
## |-- id: long (nullable = true) 
## |-- x: string (nullable = true) 
## |-- y: double (nullable = true) 

パーティションのデータのみが保存されていますシリアル化されたファイルには複製されません。これはあなたの完全な、または部分的なディレクトリツリーを読むときにのみ添付されます:

sqlContext.read.json(outdir).printSchema() 

## root 
## |-- date: string (nullable = true) 
## |-- id: long (nullable = true) 
## |-- x: string (nullable = true) 
## |-- y: double (nullable = true) 
## |-- year: integer (nullable = true) 
## |-- month: integer (nullable = true) 
## |-- day: integer (nullable = true) 

sqlContext.read.json(os.path.join(outdir, "year=2016/month=2/")).printSchema() 

## root 
## |-- date: string (nullable = true) 
## |-- id: long (nullable = true) 
## |-- x: string (nullable = true) 
## |-- y: double (nullable = true) 
## |-- day: integer (nullable = true) 
+0

私はPythonを初めて使いました。パスに年=、月=、および日=を入れずにこれを行う方法はありますか?私はこれのほとんどを理解しています – deanw