我需要在 PySpark 数据框中旋转多个列。示例数据框:
from pyspark.sql import functions as F
d = [(100,1,23,10),(100,2,45,11),(100,3,67,12),(100,4,78,13),(101,1,23,10),(101,2,45,13),(101,3,67,14),(101,4,78,15),(102,1,23,10),(102,2,45,11),(102,3,67,16),(102,4,78,18)]
mydf = spark.createDataFrame(d,['id','day','price','units'])
mydf.show()
# +---+---+-----+-----+
# | id|day|price|units|
# +---+---+-----+-----+
# |100| 1| 23| 10|
# |100| 2| 45| 11|
# |100| 3| 67| 12|
# |100| 4| 78| 13|
# |101| 1| 23| 10|
# |101| 2| 45| 13|
# |101| 3| 67| 14|
# |101| 4| 78| 15|
# |102| 1| 23| 10|
# |102| 2| 45| 11|
# |102| 3| 67| 16|
# |102| 4| 78| 18|
# +---+---+-----+-----+t
现在,如果我需要根据日期将每个 id 的价格列放入一行,那么我可以使用pivot
method:
pvtdf = mydf.withColumn('combcol', F.concat(F.lit('price_'), mydf['day'])).groupby('id').pivot('combcol').agg(F.first('price'))
pvtdf.show()
# +---+-------+-------+-------+-------+
# | id|price_1|price_2|price_3|price_4|
# +---+-------+-------+-------+-------+
# |100| 23| 45| 67| 78|
# |101| 23| 45| 67| 78|
# |102| 23| 45| 67| 78|
# +---+-------+-------+-------+-------+
因此,当我还需要将单位列转置为价格时,我必须为单位再创建一个如上所述的数据框,然后join
两者都使用“id”。但是,当我有更多这样的列时,我尝试了一个函数来做到这一点,
def pivot_udf(df, *cols):
mydf = df.select('id').drop_duplicates()
for c in cols:
mydf = mydf.join(df.withColumn('combcol', F.concat(F.lit('{}_'.format(c)), df['day'])).groupby('id').pivot('combcol').agg(F.first(c)),' id')
return mydf
pivot_udf(mydf, 'price', 'units').show()
# +---+-------+-------+-------+-------+-------+-------+-------+-------+
# | id|price_1|price_2|price_3|price_4|units_1|units_2|units_3|units_4|
# +---+-------+-------+-------+-------+-------+-------+-------+-------+
# |100| 23| 45| 67| 78| 10| 11| 12| 13|
# |101| 23| 45| 67| 78| 10| 13| 14| 15|
# |102| 23| 45| 67| 78| 10| 11| 16| 18|
# +---+-------+-------+-------+-------+-------+-------+-------+-------+
这样做是一个好的做法吗?还有其他更好的方法吗?