次のように生成されたDataFrameがあります。
_df.groupBy($"Hour", $"Category")
.agg(sum($"value").alias("TotalValue"))
.sort($"Hour".asc,$"TotalValue".desc))
_
結果は次のようになります。
_+----+--------+----------+
|Hour|Category|TotalValue|
+----+--------+----------+
| 0| cat26| 30.9|
| 0| cat13| 22.1|
| 0| cat95| 19.6|
| 0| cat105| 1.3|
| 1| cat67| 28.5|
| 1| cat4| 26.8|
| 1| cat13| 12.6|
| 1| cat23| 5.3|
| 2| cat56| 39.6|
| 2| cat40| 29.7|
| 2| cat187| 27.9|
| 2| cat68| 9.8|
| 3| cat8| 35.6|
| ...| ....| ....|
+----+--------+----------+
_
col("Hour")
のすべての一意の値に基づいて新しいデータフレームを作成したいと考えています。
したがって、望ましい出力は次のようになります。
_df0 as:
+----+--------+----------+
|Hour|Category|TotalValue|
+----+--------+----------+
| 0| cat26| 30.9|
| 0| cat13| 22.1|
| 0| cat95| 19.6|
| 0| cat105| 1.3|
+----+--------+----------+
df1 as:
+----+--------+----------+
|Hour|Category|TotalValue|
+----+--------+----------+
| 1| cat67| 28.5|
| 1| cat4| 26.8|
| 1| cat13| 12.6|
| 1| cat23| 5.3|
+----+--------+----------+
_
同様に、
_df2 as:
+----+--------+----------+
|Hour|Category|TotalValue|
+----+--------+----------+
| 2| cat56| 39.6|
| 2| cat40| 29.7|
| 2| cat187| 27.9|
| 2| cat68| 9.8|
+----+--------+----------+
_
どんな助けでも大歓迎です。
EDIT 1:
私が試したこと:
_df.foreach(
row => splitHour(row)
)
def splitHour(row: Row) ={
val Hour=row.getAs[Long]("Hour")
val HourDF= sparkSession.createDataFrame(List((s"$Hour",1)))
val hdf=HourDF.withColumnRenamed("_1","Hour_unique").drop("_2")
val mydf: DataFrame =df.join(hdf,df("Hour")===hdf("Hour_unique"))
mydf.write.mode("overwrite").parquet(s"/home/dev/shaishave/etc/myparquet/$Hour/")
}
_
この戦略の問題:
100万行を超えるデータフレームdf
で実行すると8時間かかり、sparkジョブに約10 GBが割り当てられましたRAMしたがって、join
は非常に非効率的です。
警告:各データフレームmydf
は、維持する必要がある(フラット化されていない)ネストされたスキーマを持つパーケットとして書き込む必要があります。
私のコメントで述べたように、この問題への潜在的に簡単なアプローチの1つは、以下を使用することです。
df.write.partitionBy("hour").saveAsTable("myparquet")
前述のように、フォルダー構造は、myparquet/hour=1
、myparquet/hour=2
、...、myparquet/hour=24
ではなく、myparquet/1
、myparquet/2
、...、myparquet/24
になります。
フォルダ構造を変更するには、次のことができます
hcat.dynamic.partitioning.custom.pattern
を使用する可能性があります。詳細は HCatalog DynamicPartitions を参照してください。for f in *; do mv $f ${f/${f:0:5}/} ; done
のようなものでdf.write.partitionBy.saveAsTable(...)
コマンドを実行した直後にファイルシステムを変更することです。これにより、フォルダー名からHour=
テキストが削除されます。フォルダーの名前付けパターンを変更することにより、そのフォルダーでspark.read.parquet(...)
を実行している場合、Sparkは欠落しているため、動的パーティションを自動的に理解しません。 partitionKey(つまりHour
)情報。