應(yīng)用背景
歡迎各位訪問鏈接中原創(chuàng)博客
Spark中行列轉(zhuǎn)換,即數(shù)據(jù)的透視。
以上圖為例,進(jìn)行如下定義:
- 從左邊這種變成右邊這種,叫透視(pivot)
- 反之叫逆透視(unpivot)
Spark實現(xiàn)
python、scala、java均可以進(jìn)行實現(xiàn)
構(gòu)造樣本數(shù)據(jù)
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName('JupyterPySpark').enableHiveSupport().getOrCreate()
import pyspark.sql.functions as F
# 原始數(shù)據(jù)
df = spark.createDataFrame([('2018-01','項目1',100), ('2018-01','項目2',200), ('2018-01','項目3',300),
('2018-02','項目1',1000), ('2018-02','項目2',2000), ('2018-03','項目x',999)
], ['年月','項目','收入'])
對spark dataframe進(jìn)行show格式查看
df.show()
'''
+-------+---+----+
| 年月| 項目| 收入|
+-------+---+----+
|2018-01|項目1| 100|
|2018-01|項目2| 200|
|2018-01|項目3| 300|
|2018-02|項目1|1000|
|2018-02|項目2|2000|
|2018-03|項目x| 999|
+-------+---+----+
'''
透視pivot
透視操作簡單直接,邏輯如下
- 按照不需要轉(zhuǎn)換的字段分組,本例中是年月;
- 使用pivot函數(shù)進(jìn)行透視,透視過程中可以提供第二個參數(shù)來明確指定使用哪些數(shù)據(jù)項,(可以指定不再DataFrame中schema的字段);
- 匯總數(shù)字字段,本例中是收入;
- pivot 只能跟在groupby之后
具體代碼如下:
df_pivot = df.groupBy('年月') \
.pivot('項目', ['項目1', '項目2', '項目3', '項目x', 'weizhi']) \
.agg(F.sum('收入')) \
.fillna(0)
print("============df_pivot===================")
df_pivot.show()
'''
+-------+----+----+---+---+------+
| 年月| 項目1| 項目2|項目3|項目x|weizhi|
+-------+----+----+---+---+------+
|2018-03| 0| 0| 0|999| 0|
|2018-02|1000|2000| 0| 0| 0|
|2018-01| 100| 200|300| 0| 0|
+-------+----+----+---+---+------+
'''
逆透視Unpivot
- Spark沒有提供內(nèi)置函數(shù)來實現(xiàn)unpivot操作,不過我們可以使用Spark SQL提供的stack函數(shù)來間接實現(xiàn)需求。有幾點(diǎn)需要特別注意:
- 使用selectExpr在Spark中執(zhí)行SQL片段;
- 如果字段名稱有中文,要使用反引號` 把字段包起來;
具體代碼如下:
# 逆透視Unpivot
unpivot_df = df_pivot.selectExpr("`年月`",
"stack(4, '項目1', `項目1`,'項目2', `項目2`, '項目3', `項目3`, '項目x', `項目x`) as (`項目`,`收入`)") \
.filter("`收入` > 0 ") \
.orderBy(["`年月`", "`項目`"]) \
unpivot_df.show()
'''
+-------+---+----+
| 年月| 項目| 收入|
+-------+---+----+
|2018-01|項目1| 100|
|2018-01|項目2| 200|
|2018-01|項目3| 300|
|2018-02|項目1|1000|
|2018-02|項目2|2000|
|2018-03|項目x| 999|
+-------+---+----+
'''
這個函數(shù)功能在實際的開發(fā)過程中還是很需要進(jìn)行使用的,練習(xí)一下。