雲棲號資訊:【點擊查看更多行業資訊】
在這裏您可以找到不同行業的第一手的上雲資訊,還在等什麼,快來!
在 2016 年的 Build 大會上,微軟宣佈全球有 12 億人在使用 Excel,而在同一年,全球的人口爲 74 億。也就是說,使用 Excel 的人佔全球人口的 16.2%。
2019 年的一份報告( https://slashdata-website-cms.s3.amazonaws.com/sample_reports/ZAamt00SbUZKwB9j.pdf )顯示,Python 擁有 820 萬活躍開發者,佔全球人口的 0.001%。
從這些數據可以看出,增強 Excel 和 Python 之間的交互性對我們是有好處的,這爲更多人打開了一扇使用 Python 工具的大門。
Python 在 Excel 前端方面的機會是巨大的。在本文中,我們將分享如何實現一個“典型的”財務 Excel 表格。
先工具,後 Excel
在幾乎所有我能想到的場景中,通常是先寫 Python 代碼,不過必須要保持數據“輸入”格式的靈活性。
改變輸入數據集格式不應該影響到代碼
假設我們使用 Pandas 讀取一個或兩個 CSV/Excel 表格,可能會依賴一組給定的列名。
如果有數千行這樣的代碼,我們就依賴了很多硬編碼的列名,當我們試圖使用 Excel 動態輸入列名時,就會遇到問題。
因此,在最初的原型設計階段,在還沒有使用 Excel 工作表時,可以在代碼裏將列名和內部標籤名映射起來:
mappings = {'loan identifier': 'loan_id',
'amt': 'amount',
...
'init fees': 'initial_fees'}
data.rename(mappings, axis=1, inplace=True)
稍後,這種映射將被 Excel 工作表取代。
Excel 前端
等到 Python 初具模型,就可以開始構建 Excel 前端了。首先,我們要確定哪些變量可以放在 Excel 工作表中。
在開發這類工具時,一般都是要假設輸入數據的格式是會變的。
這點要麼很重要,要麼不那麼重要,具體取決於你所在的工作環境以及你要開發什麼樣的工具。有些工作流程定義得比較好,數據格式不太可能會發生變化。
但是,我總是會傾向於保持謹慎,希望通過 Excel 來增加靈活性,但要注意不要將事情複雜化。
使用 Excel 將 Python 內部列名與外部 CSV/Excel 列名映射起來
使用內部命名系統並允許 Excel 用戶指定列映射,這是保持靈活性的一個很好的例子。現在,Excel 用戶不再依賴於硬編碼的列名,他們可以在不修改 Python 代碼的情況下調整列映射。
映射
mappings 是集成的核心部分,它的內容來自 Excel 中的一張表(我通常會叫它 Mapping)。
要得到 mappings,我們需要一個函數來讀取 Excel。爲此,我們使用了 openpyxl。
我們可以這樣讀取 Excel 中的單元格:
import openpyxl
# 加載工作簿
wb = openpyxl.load_workbook("sheet.xlsx", data_only=True)
# 創建工作簿對象
ws = wb.active
# 獲取單元格 E4 的值
value = ws['E4'].value
我們可以通過這種方式得到 mappings。我們將代碼稍作調整,添加 Excel 工作簿“tool_setup.xlsx”本地路徑。
我們還要假設 Excel 的當前工作表可能不是我們想要的那個,而且可能會新增、被刪除或被移動,所以我們需要通過遍歷找到目標工作表的索引位置:
# 首先,我們設置 Excel 文件的路徑
path = r".\documents\tool_setup.xlsx"
# 加載文件,創建工作簿對象
wb = openpyxl.load_workbook(path, data_only=True)
# 找到目標工作表的索引
idx = [i for i, name in wb.sheetnames if name == 'Mapping'][0]
# 將目標工作表設置爲當前工作表
wb.active = idx
ws = wb.active
現在,我們可以填充 mappings 內容了 :
mappings = {}
mappings['Amount'] = ws["E4"].value
mappings['Term'] = ws["E5"].value
保持靈活性
如果工作表裏添加了新行或者把舊行刪除,有可能會得到一個不正確的 mappings。爲了避免這種情況,我們需要 search_col 函數,它會遍歷查找每個單元格,直到找到包含我們想要的值(或超過 limit 限制)的單元格。
# 定義一個函數,用於查找 openpyxl 工作簿對象中的給定列
def search_col(sheet, column, value, limit=100):
# 從 1 開始,逐行查找,直到達到 limit 限制
for row in range(1, limit+1):
if sheet[f"column{row}"].value == value:
# 找到想要的單元格,返回單元格的列和行
return (col, row)
search_col 返回我們想要的數據的列和行。
如果沒處理好,哪怕是在工作表裏添加一個註釋也會讓工具不可用。左邊的“Internal”在第 12 行,而右邊是第 14 行。
我們可以像下面這樣找到“Internal”的單元格位置:
search_col(ws, 'B', 'Internal')
[Out]: ('B', 12)
接下來,我們通過循環往 mappings 添加其他列映射。在遇到兩個或者更多個空的單元格後,我們就知道映射內容已經全部讀取完畢,就可以結束循環了:
empty = 0 # 初始化空單元格數量
while empty < 2:
# 增加行計數
row += 1
# 賦值
internal = ws[f'B{row}'].value
if internal is None:
empty += 1 # 遇到空單元格就增加空單元格計數
else:
# 加入 mappings
mappings[internal] = ws[f'D{row}'].value
empty = 0 # also re-initialize the empty counter
運行上面的代碼,就可以得到像下面這樣的 mappings:
{
'Loan ID': 'loan identifier',
'Product': 'product type',
...
'Initial Fees': 'init fees'
}
如果要引入其他變量,比如文件路徑(filepath),我們只需要找到包含“Filepath”的單元格,並把它的值賦給“filepath”:
row, _ = search_col(ws, 'C', 'Filepath')
mappings['filepath'] = ws[f'D{row}].value
集成
最後一步,也是最容易的一步——在 Python 腳本中使用列名。
我們使用上面得到的 mappings,將輸入列名轉成內部標籤。
data = pd.read_csv(mappings['Filepath'])
在將輸入列名轉成內部標籤之前,我們必須翻轉鍵值對,即把鍵 - 值轉成值 - 鍵。
# 翻轉
inv_mappings = {mappings[key]: key for key in mappings}
對於這個簡單的例子,或許在構建 mappings 時就進行翻轉會更方便些。對於複雜一點的工具,我發現使用內部到外部的映射格式會更好。但不管怎樣,這一切取決於你自己。
最後,將輸入列名轉成內部標籤:
data.rename(inv_mappings, axis=1, inplace=True)
我們可以做得更靈活一些。爲了處理不必要的空格或大小寫拼寫錯誤,我們重寫了一小部分代碼:
data = pd.read_csv(mappings['Filepath'])
# 轉成小寫,剔除不必要的空格
data.rename({col: col.strip().lower() for col in data.columns},
axis=1, inplace=True)
# inv_mappings 也是一樣
# 內部標籤使用蛇形命名方式 (不是必需的)
inv_mappings = {
mappings[key].strip().lower():
key.strip().lower().replace(' ', '_')
for key in mappings
}
# 現在安全了
data.rename(inv_mappings, axis=1, inplace=True)
另外,我們在 Excel 中顯示內部標籤時通常會使用首字母大寫和正常空格,而在內部我個人還是選擇蛇形命名格式。
"Loan ID" -> "loan_id"
"Initial Rate" -> "initial_rate"
結論
我曾見過無數家重度使用 Excel 的公司,這麼做可以節省數百個小時用於檢查單元格、輸入值或等待 Excel 模型處理數據的時間。
儘管自動化和機器學習時代正在迅速地將 Excel 的很多領域自動化,但 Excel 不會很快就消失掉。
目前,世界上發展最快的編程語言(Python)和世界上使用最爲廣泛的軟件(Excel)之間的緊密集成可以給很多行業帶來巨大收益。
【雲棲號在線課堂】每天都有產品技術專家分享!
課程地址:https://yqh.aliyun.com/zhibo立即加入社羣,與專家面對面,及時瞭解課程最新動態!
【雲棲號在線課堂 社羣】https://c.tb.cn/F3.Z8gvnK
原文發佈時間:2020-08-04
本文作者:James Briggs
本文來自:“InfoQ”,瞭解相關信息可以關注“InfoQ”