在 Excel 中分析數據時,往往會用到數據透視表。通過透視表,可以對數據從不同維度、不同類別來彙總和分析。但是透視表功能很簡單,分組依據也很固化。需要將部分數據合併、分區間或者允許重複的特殊條件來分組彙總時便沒法實現。針對 Excel 透視表的分組難點,本文列出一些常用的分組示例,解析難點並提供 SPL 解決代碼。SPL 是專業計算引擎 esProc 使用的語言,用於處理結構化數據的運算非常方便。
一、常規完全分組
這裏有一份 2019 年的產品銷售表,表中記錄了每個銷售對某產品的銷售明細。現在想要按銷售員工統計出每人的銷售總量,並報告出銷售量的前三名予以嘉獎。
Excel 文件中數據如下:
期望結果:
使用 Excel 的透視表來做這種常規分析,能用但不好用。之所以說能用,是因爲使用透視表畢竟還是可以將所有數據彙總出來,然後通過排序得出名次,再複製出前三名的數據得到期望結果。但這麼多的手工操作,當數據量大,或者待保留的名次比較多時,使用起來就不那麼方便。
SPL 能遵循自然思路,分步計算:
A | B | |
1 | =clipboard().import@t() | /從剪貼板導入帶標題的銷售數據 |
2 | =A1.groups(Sale;sum(Amount):Total) | /根據銷售彙總,統計出每個銷售的銷售總量 Total |
3 | =A2.top(-3;Total) | /只取銷售總量前三名 |
4 | =A3.derive(#:Rank) | /增加一個排名字段 |
5 | =clipboard(A4.export@t()) | /將彙總結果放回到剪貼板 |
代碼執行完成後,只需在Excel 中粘貼便可得到期望結果。
本文中 SPL 示例,都通過剪貼板跟 Excel 進行數據交互。首先從 Excel 中將要分析的數據複製到剪貼板,然後在集算器設計器裏編輯 SPL 腳本,最後執行代碼,並在 Excel 中粘貼計算結果。
二、併入“其它”
有時候,並不希望統計每一明細數據。而是隻關注其中一部分,其餘的全部合併。比如上例中按產品分組統計時,只關注每種水果的銷量,其他的蔬菜則全部合併統計。
期望結果:
這種依賴具體數據的合併要求,使用透視表沒法做出。只能去寫 VBA 宏,用程序針對特定數據分組,麻煩且有一定難度。
SPL 可以採用具體枚舉值來進行劃分:
A | B | |
1 | =clipboard().import@t() | /從剪貼板導入銷售記錄 |
2 | =A1.align@an(["Orange","Grape","Apple","Banana","Strawberry"],Product) | /根據水果列表,將銷售記錄分組,並且使用 n 選項,將其他歸爲一組 |
3 | =A2.new(Product,~.sum(Amount):Total) | /計算每組總銷量,產生新的序表 |
4 | =A3(A3.len()).Product="Others" | /將最後一項的其他產品名稱改爲 Others |
5 | =clipboard(A3.export@t()) | /將結果導出後放置到剪貼板 |
執行結束後,在Excel 中粘貼,便可得到期望結果。
三、補充對齊
透視表只能根據數據做常規分組,對於空缺的數據,不會產生相應分組。比如對銷量表按日期分組時,由於部分月份沒有銷售記錄,因此使用透視表分組後得到的結果爲:
其中 3 月等沒有數據的月份,也沒有相應分組,結果看起來不整齊,現在想要這樣的結果:
這種需求,透視表仍然沒法做到。寫 VBA 代碼實現的難度跟上一節類似。
SPL 可以使用條件分組,事先預置出分組類別:
A | B | |
1 | =clipboard().import@t() | /從剪貼板導入銷售記錄 |
2 | =A1.run(Date=date(Date,"yyyy/MM/dd")) | /將串型日期字段轉換爲日期類型 |
3 | =A2.align@a(12,month(Date)) | /將日期按照固定的 12 個月來分組 |
4 | =A3.new(#:Month,~.sum(Amount):Total) | /統計分組後的數據,產生新的序表 |
5 | =clipboard(A4.export@t()) | /將結果導出後放置到剪貼板 |
四、按區間分組
如下爲學生的考試成績表,現在需要根據分數所屬區間,比如 60 分以下評爲 C,90 分以下評爲 B,90 以上評爲 A,然後按照區間評級統計各分數段的人次。
考生的成績表:
期望結果:
按照成績劃分區間段來分組時,定義好值的劃分區間後,只需用 pseg 函數便可以將分數分好段,然後統計出各段人次即可。
SPL 代碼如下:
A | B | |
1 | =clipboard().import@t() | /從剪貼板導入分數表 |
2 | =[0,60,90] | /定義分數分段區間 |
3 | =["C","B","A"] | /定義對應區間名稱 |
4 | =A1.align@a(A2.len(),A2.pseg(Score)) | /算出成績所在段,按照段分組 |
5 | =A4.new(A3(#):Level,~.count():Count) | /統計各段人次,產生新序表 |
6 | =clipboard(A5.export@t()) | /將導出結果放置到剪貼板 |
五、可重疊分組
如下爲 2019 年部分國家的 GDP 產值。現在想按發達國家,發展中國家以及金磚五國分類,計算一下各類的平均 GDP。
2019 年部分國家 GDP 數據 (單位:億美元):
期望結果:
可以看到,其中的發展中國家跟金磚五國,是有重複數據的。像這種重複劃分的需求,可以使用 enum 枚舉函數,通過對數值的枚舉,可以很自由地定義分組條件。
SPL 代碼:
A | B | |
1 | =clipboard().import@t() | /從剪貼板導入國家 GDP 產值表 |
2 | ["America","Japan","Germany","Britain","France","Italy","Canada","Korea","Australia"].pos(?)>0 | /枚舉出發達國家 |
3 | ["China","India","Mexico","SouthAfrica"].pos(?)>0 | /枚舉發展中國家 |
4 | ["Brazil","Russia","India","China","South Africa"].pos(?)>0 | /枚舉金磚五國 |
5 | =[A2:A4] | /構造枚舉條件序列 |
6 | =["Developed","Developing","BRICS"] | /枚舉條件的對應名稱 |
7 | =A1.enum@r(A5,Country) | /使用枚舉函數對國家分組,注意如果允許重複數值的分組,要帶上選項 r |
8 | =A7.new(A6(#):Countries,~.avg(GDP):Average) | /對分組後的數值計算平均 GDP,併產生新序表 |
9 | =clipboard(A8.export@t()) | /將結果導出並放置到剪貼板 |