話說Excel數據表,分久必合、合久必分。Excel數據表的“分”與“合”是日常辦公中常見的操作。手動操作並不困難,但數據量大了之后,重復性操作往往會令人崩潰。利用Python的Pandas庫,便可以自動實現Excel數據表的“分分合合”。下面結合實例來分享本人整理的實用代碼片段。(如有更好的方式,歡迎批評指正)

分:縱向“分”
從數據平台(如問卷平台)中導出的數據往往是清單型的,每一行都是一條記錄,數據量大的時候,表格往往是很“長”的。有時需要按照某列的不同數值,將一個總表“分”成單獨的一些Excel文件。

一個工作表“分”為多個Excel文件
def to_excelByColName(sourceDf,colName,outPath,excelName):
'''
縱向“分”:一個工作表“分”為多個Excel文件
根據指定的列名中的不同值,分解Excel,並存儲成多個Excel文件。
sourceDf:原始的DataFrame
colName:指定列名
outPath:輸出路徑
excelName:文件名,加.xlsx后綴
'''
colNameList = sourceDf[colName].drop_duplicates().tolist()
for eachColName in colNameList:
sourceDf[sourceDf[colName]==eachColName].to_excel('/'.join([outPath,eachColName+excelName]),index=False)
例如:將20個班級1000名學生的總表,按班級分成20個Excel文件。
調用to_excelByColName
函數,效果如下:
to_excelByColName(sourceDf = sourceDf,colName="班級",outPath=".\分班數據表",excelName="生成數據表.xlsx")

一個工作表“分”為一個文件的多個sheet
def to_excelByColNameWithSheets(sourceDf,colName,outPath):
'''
縱向“分”:一個工作表“分”為一個文件的多個sheet
根據指定的列名中的不同值,分解Excel,並存儲成單個Excel文件的多個Sheet。
sourceDf:原始的DataFrame
colName:指定列名
outPath:輸出路徑,加.xlsx后綴
'''
writer = pd.ExcelWriter(outPath)
colNameList = sourceDf[colName].drop_duplicates().tolist()
for eachColName in colNameList:
sourceDf[sourceDf[colName]==eachColName].to_excel(writer,sheet_name=eachColName)
writer.save()
例如:將20個班級1000名學生的總表,按班級分成1個Excel文件的20個sheet表。
調用to_excelByColNameWithSheets
函數,效果如下:
to_excelByColNameWithSheets(sourceDf = sourceDf,colName="班級",outPath=".\分班數據表\生成數據表.xlsx")

分:橫向“分”
在處理數據的時候,有時需要添加多個輔助列,這樣也會讓數據表越來越“寬”。而最終我們只需要某些關鍵列即可,那么這就涉及到橫向數據分割,或者說提取某些列保持成一個單獨的數據表。橫向的分割只需要給DataFrame傳入列名列表即可。
例如:只需要數據表中的姓名和班級字段,可以這樣寫。
df1 = sourceDf[["姓名","班級"]]
df1.to_excel("只含有姓名和班級的數據表.xlsx")
合:縱向“合”
對於結構相同的數據,在數據處理時可以將其在縱向上拼接,方便一起處理。

多個Excel文件合並成一個工作表
def readExcelFilesByNames(fpath,fileNameList=[],header=0):
'''
縱向“合”:多個Excel文件合並成一個工作表
讀取路徑下指定的Excel文件,並合並成一個總的DataFrame。
每個Excel文件的數據表格式上要一致。
1.fpath:必填,是Excel文件所在路徑,不加文件名
2.fileNameList:需要讀取的Excel文件名列表
3.header:指定讀取的行數
'''
outdf = pd.DataFrame()
for fileName in fileNameList:
tempdf =pd.read_excel('/'.join([fpath,fileName]),header = header)
outdf = pd.concat([outdf,tempdf])
return outdf
例如:將20個班級的Excel文件,合並成一個數據表
調用readExcelFilesByNames
函數,效果如下:
fileNameList = [
"六1班數據表.xlsx", "六2班數據表.xlsx", "六3班數據表.xlsx", "六4班數據表.xlsx",
"六5班數據表.xlsx", "六6班數據表.xlsx", "六7班數據表.xlsx", "六8班數據表.xlsx",
"六9班數據表.xlsx", "六10班數據表.xlsx", "六11班數據表.xlsx", "六12班數據表.xlsx",
"六13班數據表.xlsx", "六14班數據表.xlsx", "六15班數據表.xlsx", "六16班數據表.xlsx",
"六17班數據表.xlsx", "六18班數據表.xlsx", "六19班數據表.xlsx", "六20班數據表.xlsx",
]
readExcelFilesByNames(fpath = ".\分班數據表",fileNameList=fileNameList)

多個Sheet合並成一個工作表
def readExcelBySheetsNames(fpath,header = 0,prefixStr = "",sheetNameStr ="sheetName",prefixNumStr = "prefixNum"):
'''
縱向“合”:多個Sheet合並成一個工作表
讀取所有的Excel文件的sheet,並合並返回一個總的DataFrame。
每個sheet的數據表格式上要一致。
1.fpath:必填,是Excel文件的路徑,加文件名
2.會生成兩個新列:sheetName和prefixNum,方便數據處理
sheetName列是所有sheet的名稱列
prefixNum列是計數列
3.header:指定讀取的行數
'''
xl = pd.ExcelFile(fpath)
# 獲取Excel文件內的所有的sheet名稱
sheetNameList = xl.sheet_names
outfd = pd.DataFrame()
num = 0
for sheetName in sheetNameList:
num += 1
data = xl.parse(sheetName,header=header)
# 產生sheet名稱列和計數列
data[sheetNameStr] = sheetName
data[prefixNumStr] = prefixStr +str(num)
# 數據表拼接
outfd = pd.concat([outfd,data.dropna()])
xl.close()
return outfd
如下調用readExcelBySheetsNames
,運行效果如下:
readExcelBySheetsNames(fpath = ".\分班數據表\總數據表.xlsx",sheetNameStr ="sheet名",prefixNumStr = "sheet序號")

合:橫向“合”
對於不同Excel工作表之間的橫向合並,主要是用根據某些列(如:姓名、身份證號等)進行合並。在pandas庫中可以用merge
方法來實現,這是個十分好用的方式,展開講篇幅較長,后續詳細整理。
DataFrame.merge(right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'), copy=True, indicator=False, validate=None)
結語
本文所談的Python處理Excel文件方式主要是基於pandas
庫的,主要針對的是清單型的數據表
。清單型的數據表在下面的文章中有詳細介紹:
https://www.cnblogs.com/wansq/p/15869594.html
數據表的分
主要涉及的是文件保存(寫入),對程序來說屬於輸出
環節;
數據表的合
主要針對的是文件打開(讀取),對程序而言屬於輸入
環節。
以上代碼在針對大量重復性的表格分與合時,優勢巨大;但對於偶爾、少量的分與合,也許用鼠標點擊更快。
技術沒有好壞之分,需要靈活使用!
