2016-02-16 29 views
8

Tôi đang sử dụng PySpark để thực hiện công việc ETL cổ điển (tải tập dữ liệu, xử lý, lưu) và muốn lưu Dataframe của tôi dưới dạng tệp/thư mục được phân đoạn bằng cột "ảo" ; ý tôi là "ảo" là tôi có một Dấu thời gian cột là một chuỗi chứa ngày được mã hóa theo ISO 8601 và tôi muốn phân vùng theo Năm/Tháng/Ngày; nhưng tôi không thực sự có cột Năm, Tháng hoặc Ngày trong DataFrame; Tôi có Dấu thời gian này mà từ đó tôi có thể lấy được các cột này, nhưng tôi không muốn các mục kết quả của tôi có một trong các cột này được tuần tự hóa.Spark: lưu DataFrame được phân đoạn bằng cột "ảo"

cấu trúc tập tin thu được từ tiết kiệm DataFrame vào đĩa nên hình như:

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

Có cách nào để làm những gì tôi muốn với Spark/Pyspark?

Trả lời

15

Cột được sử dụng để phân đoạn không được bao gồm trong chính dữ liệu được tuần tự hóa. Ví dụ, nếu bạn tạo DataFrame như thế này:

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

và viết nó như sau:

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)) 

tập tin cá nhân sẽ không chứa các cột phân vùng: Dữ liệu

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) 

Phân vùng được lưu trữ chỉ trong cấu trúc thư mục và không được nhân bản trong các tệp được tuần tự hóa. Nó sẽ được đính kèm chỉ khi cây thư mục hoàn chỉnh hoặc một phần của bạn đọc:

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

Tôi mới dùng python. Có cách nào để làm điều này mà không có năm =, tháng =, và ngày = trong đường dẫn? Tôi hiểu hầu hết điều này – deanw

Các vấn đề liên quan