大家好,又到了Python辦公自動化專題。
在之前我們詳細講解過如何使用Python自動更新Excel表格並調整樣式,在上次的自動化案例中要求兩個或多個Excel表格數據要匹配/對稱才能夠自動更新,今天我們再次來解決在數據不對稱的情況下如何自動更新表格,這是更常見的情況,也是我遇到的一個具體需求。
需求分析
現在我們有類似如下一份記錄了口袋妖怪名字的分組名單:(未全部展示,實際有A-U組+1個"未分組")
現在有一份更新的名單(僅含名字)
需要根據這份新名單對原來的總表進行更新,即對新名單中的名字按照總表的分組進行更新,剔除不在新名單中的名字,並將新名單中新出現的名字劃分到“未分組”中,如上圖中的“早小起”
這位讀者的需求是一個需要長期重複的任務,每隔一段時間就會拿到一個新名單,需要對總名單進行調整。如果用Excel操作,可能需要反覆查找新名單的名字在哪個分組,如果不存在則手動添加到“未分組”,存在則做標記。最後把未做標記的名字刪除再刪除空隙即可,整個過程十分繁瑣,而且若總名單有千萬個名字則工作量非常大。因此該工作很適合用Python輔助自動化
Python實現
第一步是導入需要的庫並把路徑設置好,我還是習慣用函數定位到桌面上利於複用
import os
import pandas as pd
import numpy as np
def GetDesktopPath():
return os.path.join(os.path.expanduser("~"), 'Desktop')
path = GetDesktopPath() + '\\data\\'
接着讀取兩份文件
df1 = pd.read_excel(path + '總名單.xlsx',encoding = 'utf-8',sheet_name = 0,skiprows=1)
df2 = df1.iloc[:,1:23]
df3 = pd.read_excel(path + '新名單.xlsx',encoding = 'utf-8',sheet_name = 0)
接下來是根據新名單中出現的名字找各自在總表中的分組,思路是用np.where
,如下所示
np.where(df2 == '死神板')
# (array([7], dtype=int64), array([5], dtype=int64))
返回元組,行列信息都在裏面,那麼用如下命令即可獲得口袋妖怪“死神板”所在的分組
col = np.where(df2 == '死神板')[1][0]
df2.columns[col]
# 'F組'
有了個思路就可以寫個函數,並用apply
逐個運用到新名單裏的名字上
這裏要注意,新名單中的名字在總名單中可能沒有,因此需要判斷後再取最裏面一層數字,否則會出錯
def find(x):
results = np.where(df2 == x)[1]
try:
return df2.columns[results[0]]
except:
return '未分組'
df3['備註'] = df3['最新名單'].apply(find)
接下來這個操作就是根據分組把上面的數據框“劈開”
results_lst = []
for index,i in enumerate(df2.columns):
results = df3.iloc[np.where(df3['備註']==i)[0].tolist(),0]
# 重置索引很重要,爲什麼重要往下看
results = results.reset_index(drop=True)
results_lst.append(results)
results_lst
可以看到,結果是一個Series列表,這不正好是pd.concat
的對象嘛,由於接下來要橫向合併,因此每個Series需要重置索引保證都是從0開始
df_final = pd.concat(results_lst,axis=1)
# 記得把列名還原
df_final.columns = df2.columns
整個需求就大致完成了 (兩個非口袋妖怪的生物也被識別出來了)
df_final.to_excel(f'{path}整理後表格.xlsx',
encoding='gbk', # 編碼不一定是gbk
index=False,
header=True)
最後就是保存並將結果以excel形式輸出,如上圖所示,我們就使用Python成功完成了一次Excel非對稱表格的自動更新,接下來應該使用openpyxl
進行樣式的修改,而這一部分在之前的文章中有很詳細的講解,本文就不再展開。