PySpark DataFrame透视后自定义月份排序异常问题
PySpark透视表月份列排序异常解决方案
问题根源:你将月份数字转换为缩写字符串后,pivot默认会按字符串字典序排列列,而非月份的自然时间顺序,导致排序异常。
解决方案一:先按数字月份透视,再替换列名
这种方法利用数字月份的自然排序保证列顺序正确,之后再将列名替换为月份缩写:
import pyspark.sql.functions as F # 保留数字月份,不转换为字符串 DF = MonthsDF\ .dropna(subset=["trip_start_time"])\ .withColumn("Month", F.month("trip_start_time")) # 按数字月份透视,此时列会按1-12自然排序 MyDF = DF.groupBy("Hour").pivot("Month").count().orderBy("Hour") # 定义数字到月份缩写的映射 month_mapping = { 1: "JAN", 2: "FEB", 3: "MAR", 4: "APR", 5: "MAY", 6: "JUN", 7: "JUL", 8: "AUG", 9: "SEP", 10: "OCT", 11: "NOV", 12: "DEC" } # 重命名列,并确保列顺序正确 new_cols = ["Hour"] + [month_mapping[int(col)] for col in MyDF.columns if col != "Hour"] MyDF = MyDF.toDF(*new_cols)
解决方案二:透视时指定列顺序
直接在pivot方法中传入按时间顺序排列的月份缩写列表,强制指定列的顺序:
import pyspark.sql.functions as F # 完整转换所有月份为缩写 DF = MonthsDF\ .dropna(subset=["trip_start_time"])\ .withColumn("Month", F.month("trip_start_time"))\ .withColumn("Month", F.when(F.col("Month") == 1, "JAN") .when(F.col("Month") == 2, "FEB") .when(F.col("Month") == 3, "MAR") .when(F.col("Month") == 4, "APR") .when(F.col("Month") == 5, "MAY") .when(F.col("Month") == 6, "JUN") .when(F.col("Month") == 7, "JUL") .when(F.col("Month") == 8, "AUG") .when(F.col("Month") == 9, "SEP") .when(F.col("Month") == 10, "OCT") .when(F.col("Month") == 11, "NOV") .when(F.col("Month") == 12, "DEC") ) # 定义按时间顺序排列的月份缩写列表 ordered_months = ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"] # 透视时传入指定的列顺序 MyDF = DF.groupBy("Hour").pivot("Month", ordered_months).count().orderBy("Hour")
两种方案都能解决月份排序问题,方案一不需要写全所有when条件,更简洁;方案二则直接基于字符串月份处理,逻辑更直观。
内容的提问来源于stack exchange,提问作者Ruben
相关产品推荐
相关产品推荐

