防止 DataFrame.partitionBy() 从架构中删除分区列

Prevent DataFrame.partitionBy() from removing partitioned columns from schema

我正在对 DataFrame 进行如下分区:

df.write.partitionBy("type", "category").parquet(config.outpath)

代码给出了预期的结果(即按类型和类别划分的数据)。但是,"type" 和 "category" 列已从数据/模式中删除。有没有办法防止这种行为?

我能想到一个变通办法,虽然有点蹩脚,但很管用。

import spark.implicits._

val duplicated = df.withColumn("_type", $"type").withColumn("_category", $"category")
duplicated.write.partitionBy("_type", "_category").parquet(config.outpath)

我回答这个问题是希望有人能比我有更好的答案或解释(如果 OP 找到了更好的解决方案),因为我有同样的问题。

总的来说,Ivan 的回答很不错。但是...

如果你是严格在spark中读写,你可以在读取数据时使用basePath选项。

https://spark.apache.org/docs/2.2.0/sql-programming-guide.html#partition-discovery

By passing path/to/table to either SparkSession.read.parquet or SparkSession.read.load, Spark SQL will automatically extract the partitioning information from the paths.

示例:

     val dataset = spark
      .read
      .format("parquet")
      .option("basePath", hdfsInputBasePath)
      .load(hdfsInputPath)

我想在这里添加更多上下文,并为需要它的人提供 PySpark 代码而不是 Scala。如果要保留分区变量(细节很重要),则需要注意如何读取分区数据框。让我们从编写这样的分区数据框开始:

df.write.mode("overwrite").partitionBy("Season").parquet("partitioned_parquet/")

要使用包含的分区变量读回整个数据帧...

path = "partitioned_parquet/"
parquet = spark.read.parquet(path)
parquet.show()

结果:

+-----+------+
|Value|Season|
+-----+------+
|   71|  2010|
|   77|  2010|
|   83|  2010|
|   54|  2010|
|  100|  2010|
+-----+------+
only showing top 5 rows

请注意,如果您在路径名末尾包含 *,分区变量 将被删除

path = "partitioned_parquet/*"
parquet = spark.read.parquet(path)
parquet.show(5)

结果:

+-----+
|Value|
+-----+
|   71|
|   77|
|   83|
|   54|
|  100|
+-----+
only showing top 5 rows

现在,如果您只想读取 分区数据帧的部分 ,则需要使用此方法来保留您的分区变量(在本例中 "Season").

path = "partitioned_parquet/"
dataframe = spark.read.option("basePath", path).parquet(path+'Season=2010/',\
                                                                path+'Season=2011/', \
                                                                path+'Season=2012/')
dataframe.show(5)

结果:

+-----+------+
|Value|Season|
+-----+------+
|   71|  2010|
|   77|  2010|
|   83|  2010|
|   54|  2010|
|  100|  2010|
+-----+------+
only showing top 5 rows

希望对大家有所帮助!