問題描述
在工作中時常會遇到對 Excel 表格的處理。當編輯一張 Excel 表格時,發現表格的列數太多,而行數較少,為友善列印,這時你或許會希望将該表格行列轉換;或許是為了做進一步做統計分析,目前格式不太友善,這時也會用到行列轉換。
下面這種交叉式的 Excel 表是很常見的格式,用來填寫和檢視都比較友善:

顯然,手工操作會非常麻煩,若資料量小還可以,資料量大了會耗費大量時間,簡直就是災難。
我們就以此為例,舉例說明幾種常見的解決方法。
解決方法
方法 1:Excel 資料透視表
Excel 可以通過資料透視表支援行列轉換功能,效果如下圖:
顯然,這并不是我們想要的格式。Excel 的資料透視表可以滿足簡單格式的行列轉換,但如果格式稍微複雜,轉換效果往往是不盡人意。
方法 2:程式設計語言
以寫程式來解決,思路也很簡單:
· 加載 excel 檔案,裝載需要的 sheet 工作表。
· 讀取“賬套名”所在行,将其轉換成字元串數組。
· 讀取“科目編碼”所在列,将其轉換成字元串數組。
· 按“科目編碼”分組,與“賬套名”數組構造一張表。
· 根據“賬套名”對應的資料,周遊所有的明細值填充到相應的表中。
· 這樣就可以構造出對應的明細表來。
如果用 Java 來實作,初步估計代碼量也不會少于 200 行,若需要結果輸出成 excel 檔案則開發工作量會更多。雖然 Excel 自己提供了 VBA,但那個麻煩程度誰用誰知道,不提也罷。那其它的語言呢?傳說 python 有處理行列轉換的功能(pandas 包裡有 pivot 功能),代碼量相對于 java 會少很多, 我們來試一下:
import pandas as pd
import numpy as np
df = pd.read_excel("D:\\excel\\pandas.xlsx", 0, 3)
cols = df.columns.values.tolist() #擷取資料頭資訊
#移去前兩列,隻保留需要行列轉換的列
cols.remove('科目編碼')
cols.remove('科目明細')
#構造一個 list.
frames=[]
for col in cols:
df1 = df.pivot_table(index = ['科目編碼','科目明細'], values = [col])
df1.rename(columns={col: '數值'}, inplace=True)
df1[3]=col
#轉換後的資料追加到 frames 中.
frames.append(df1)
# concat 将相同字段的表首尾相接
result=pd.concat(frames)
result.rename(columns={3: '帳套名'}, inplace=True)
result.to_excel('D:\\excel\\pandas_n.xlsx', sheet_name='科目明細')
效果還不錯,果然比較簡潔!這是 Python 生成的 excel 檔案:
不過,存在一點小問題,這個 excel 格式有點特殊,想用 Python 的 pivot,我們要将“科目編碼”,“科目明細”移到與轉換列标題所在同一行上,變成下面的樣子。否則在代碼上就得特殊 “照顧”,反正隻有一行,手工做一下就算了,比寫代碼省事。
無論如何,python 的這個細節處理的小“瑕疵”并不影響其友善性。python 确實名不虛傳,雖然使用了循環,但整個代碼也就隻有 10 來行的樣子。
還能更簡單嗎?
嘿嘿,能!
方法 3:集算器程式設計
下面我們來看集算器的代碼:
代碼很簡單,我們把每一步的中間結果列出來看看:
A1:加載 excel 檔案工作表 1,提取指定範圍的資料 (從 3 行到 40 行),其中選項 @ t 表示首行為标題,載入資料, 生成表格如下:
A2:删除非資料行
A3:更換列名稱
A4:把從第 3 列開始的列名稱連成字元串,用“,”分開
A5:pivot 函數将行列資料進行轉換,把 A4 中對應的列資料置放到“數值”列
A6:将整理好的資料另存儲為 xlsx 檔案
集算器腳本隻有 6 行,木有啥循環、判斷之類的玩意兒,也不像 Python 那樣要先手工倒騰一下,就把這看似有點“亂”的資料表格處理好了。相比之下,Python 采用列優先轉換多次循環 “N”字方式,集算器則用行優先一次性處理,在處理資料上,集算器對細節處理及使用習慣更專業。而且集算器的開發環境也容易調試,可以看到每一步運算的中間結果,友善挑出錯誤,開發更為便捷。在這種正常資料處理的任務中,集算器要比 Python 更為優越。
優勢總結
就這個問題,關于 python 與集算器的差異,再說說自己的一點心得體會:
-
多列轉換
對于需要多列行列轉換并彙內建“長”列的場景時,python 需要将每個資料列構造成數組,并增加一列記錄目前列名,再追加到一個大的清單中,最後合并,合并中去掉非首個數組中的 title;
集算器就容易些,它直接把想要轉換的列彙集在一塊就行。相對于 python 的繁瑣,集算器至少能省幾個腦細胞。
-
名稱更改
python 對于需要轉換列的名稱不能更改, 如 cols[0]=’天津’,此時 python 找不到修改前的關鍵字,“哪個朋友挖的坑,别以為我發現不了”,欺負大爺眼花,給報個異常行不?
但對應的集算器來說則很友善, 如:>A1.rename(_1: 科目編碼,_2: 科目明細,4 成都: 成都)
-
标題空值問題
Python 讀取 excel 表中的轉換行标題時,前面兩列為空 (對應原來的 excel 中的“科目編碼,科目明細”),此時标題 cols 中的空值就沒有了, 這個“坑”有點隐蔽啊,我真沒有發現, 把其中的兩列弄丢了,真有點丢臉 ;
但集算器能識别出來,會自動加上對應的辨別 _1、_2,這樣處理資料時,就能找到其中對應的兩列。
-
網格式程式設計
集算器使用網格 A1 這種格式,它自動與所在位置的對象關聯起來,這點非常友善, 感覺很有特色;Python 就隻能望洋興歎了。