天天看點

Excel 行列轉換的最簡方法

問題描述

  在工作中時常會遇到對 Excel 表格的處理。當編輯一張 Excel 表格時,發現表格的列數太多,而行數較少,為友善列印,這時你或許會希望将該表格行列轉換;或許是為了做進一步做統計分析,目前格式不太友善,這時也會用到行列轉換。

  下面這種交叉式的 Excel 表是很常見的格式,用來填寫和檢視都比較友善:

Excel 行列轉換的最簡方法
 但是,如果想做進一步的統計分析,這種格式就不友善了,需要行列轉換,變成如下格式的明細表:
Excel 行列轉換的最簡方法

 顯然,手工操作會非常麻煩,若資料量小還可以,資料量大了會耗費大量時間,簡直就是災難。

  我們就以此為例,舉例說明幾種常見的解決方法。

解決方法

方法 1:Excel 資料透視表

  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 行列轉換的最簡方法

不過,存在一點小問題,這個 excel 格式有點特殊,想用 Python 的 pivot,我們要将“科目編碼”,“科目明細”移到與轉換列标題所在同一行上,變成下面的樣子。否則在代碼上就得特殊 “照顧”,反正隻有一行,手工做一下就算了,比寫代碼省事。

Excel 行列轉換的最簡方法

 無論如何,python 的這個細節處理的小“瑕疵”并不影響其友善性。python 确實名不虛傳,雖然使用了循環,但整個代碼也就隻有 10 來行的樣子。

  還能更簡單嗎?

  嘿嘿,能!

方法 3:集算器程式設計

  下面我們來看集算器的代碼:

Excel 行列轉換的最簡方法

 代碼很簡單,我們把每一步的中間結果列出來看看:

  A1:加載 excel 檔案工作表 1,提取指定範圍的資料 (從 3 行到 40 行),其中選項 @ t 表示首行為标題,載入資料, 生成表格如下:

Excel 行列轉換的最簡方法

A2:删除非資料行

  

Excel 行列轉換的最簡方法

 A3:更換列名稱

Excel 行列轉換的最簡方法

 A4:把從第 3 列開始的列名稱連成字元串,用“,”分開

Excel 行列轉換的最簡方法

A5:pivot 函數将行列資料進行轉換,把 A4 中對應的列資料置放到“數值”列

Excel 行列轉換的最簡方法

A6:将整理好的資料另存儲為 xlsx 檔案

Excel 行列轉換的最簡方法

 集算器腳本隻有 6 行,木有啥循環、判斷之類的玩意兒,也不像 Python 那樣要先手工倒騰一下,就把這看似有點“亂”的資料表格處理好了。相比之下,Python 采用列優先轉換多次循環 “N”字方式,集算器則用行優先一次性處理,在處理資料上,集算器對細節處理及使用習慣更專業。而且集算器的開發環境也容易調試,可以看到每一步運算的中間結果,友善挑出錯誤,開發更為便捷。在這種正常資料處理的任務中,集算器要比 Python 更為優越。

優勢總結

  就這個問題,關于 python 與集算器的差異,再說說自己的一點心得體會:

  1. 多列轉換

      對于需要多列行列轉換并彙內建“長”列的場景時,python 需要将每個資料列構造成數組,并增加一列記錄目前列名,再追加到一個大的清單中,最後合并,合并中去掉非首個數組中的 title;

  集算器就容易些,它直接把想要轉換的列彙集在一塊就行。相對于 python 的繁瑣,集算器至少能省幾個腦細胞。

  1. 名稱更改

      python 對于需要轉換列的名稱不能更改, 如 cols[0]=’天津’,此時 python 找不到修改前的關鍵字,“哪個朋友挖的坑,别以為我發現不了”,欺負大爺眼花,給報個異常行不?

  但對應的集算器來說則很友善, 如:>A1.rename(_1: 科目編碼,_2: 科目明細,4 成都: 成都)

  1. 标題空值問題

      Python 讀取 excel 表中的轉換行标題時,前面兩列為空 (對應原來的 excel 中的“科目編碼,科目明細”),此時标題 cols 中的空值就沒有了, 這個“坑”有點隐蔽啊,我真沒有發現, 把其中的兩列弄丢了,真有點丢臉 ;

  但集算器能識别出來,會自動加上對應的辨別 _1、_2,這樣處理資料時,就能找到其中對應的兩列。

  1. 網格式程式設計

      集算器使用網格 A1 這種格式,它自動與所在位置的對象關聯起來,這點非常友善, 感覺很有特色;Python 就隻能望洋興歎了。