話說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
資料表的分
主要涉及的是檔案儲存(寫入),對程式來說屬於輸出
環節;
資料表的合
主要針對的是檔案開啟(讀取),對程式而言屬於輸入
環節。
以上程式碼在針對大量重複性的表格分與合時,優勢巨大;但對於偶爾、少量的分與合,也許用滑鼠點選更快。
技術沒有好壞之分,需要我們靈活使用!
關注公眾號“位元組雜談”,
回覆“分分合合”即可下載本文的程式碼,
開箱即用!