在pyspark中,当使用df.write.partitionBy(..)。save时如何对某个列的值的一部分进行分区?

时间:2019-06-25 07:04:37

标签: apache-spark pyspark apache-spark-sql

我想在Spark Dataframe中按日期而不是时间进行分区,该怎么做?

假设我具有第一列作为日期时间的数据框,例如“ 2019-06-25 12:00:00”,“ 2019-06-25 11:00:00”,依此类推。我知道如何分割时间,但我不知道如何按日期对其进行分区。

spark = SparkSession.builder.getOrCreate()

df = spark.sparkContext.parallelize([
    Row("2019-06-25 12:00:00", "2"), Row("2019-06-25 11:00:00", "a"),
    Row("2019-06-24 02:03:10", "2"), Row("2019-06-22 08:00:00", "b"),
    Row("2019-03-12 08:01:34", "3")]).toDF(["datetime", "val"])
+-------------------+---+
|               date|val|
+-------------------+---+
|2019-06-25 12:00:00|  2|
|2019-06-25 11:00:00|  a|
|2019-06-24 02:03:10|  2|
|2019-06-22 08:00:00|  b|
|2019-03-12 08:01:34|  3|
+-------------------+---+

我想使用这样的方法

df.write.partitionBy(substr('datetime', 10)).save(path='...', mode='...')

实现我的目标,但是上述方法显然行不通。

1 个答案:

答案 0 :(得分:2)

在这种情况下,您可以简单地基于“ datetime”字段添加一个新列,比如说“ date_only”

您的代码段就像

1)从源SQL或任何平面文件系统等中注册数据框。在这种情况下,让我们考虑以下顺序。

df = spark.sparkContext.parallelize([
    ("2019-06-25 12:00:00", "2"), ("2019-06-25 11:00:00", "a"),
    ("2019-06-24 02:03:10", "2"), ("2019-06-22 08:00:00", "b"),
    ("2019-03-12 08:01:34", "3")]).toDF(["datetime", "val"])

2)从源头准备一个新的数据框,这将使您拥有一个新列,而现有列也不会从分区中的结果文件中删除。

from pyspark.sql import functions as func
partitioned_df = df.withColumn("date_only", func.to_date(func.col("datetime")))

3)以“追加”模式将数据保存到这些分区中。

partitioned_df.write.partitionBy('date_only').save(path='dbfs:/FileStore/tables/Temp', mode='append')

4)我在Databricks中尝试了以下操作,分类法如下所示:

Databricks File System - LS result

5)Parquet(Snappy)文件也包含如下结果:

Sample file Partitioned in Parquet format

请告诉我是否可以解决您的问题。