?用 Python 讓 Excel 表格合并飛起來
來源:Python數(shù)據(jù)之道
作者:Lee
問題提出
我們?cè)诠ぷ髦薪?jīng)常會(huì)遇到如下情況,從不同部門或者不同單位收集到若干個(gè)表格,每個(gè)表格的內(nèi)容相同(列內(nèi)容一致),需要將他們匯總到同一個(gè)表格中。Python 作為數(shù)據(jù)分析的神器,只需要簡(jiǎn)單行代碼就可以讓表格合并飛起來,并且代碼可以多次復(fù)用。
解法1
用 Python 循環(huán)進(jìn)行自動(dòng)合并
閑話少說,直接上代碼了。
import pandas as pd
import time
filelist = ['c:/python/aSourseFiles/bi/bi (' + str(i+1) + ').xlsx' for i in range(40)] #需要打開的文件列表,如果要自己運(yùn)行代碼,找一個(gè)excel復(fù)制40遍再重命名就行了。
start = time.time() #用于計(jì)時(shí)。
df = pd.read_excel(filelist[-1]) #以最后一個(gè)文件為基礎(chǔ)進(jìn)行合并操作
for i in range(39): #將其余39個(gè)文件與最后一個(gè)合并
df = pd.concat([df, pd.read_excel(filelist[i])])
print(i)
end = time.time()
run_time = end - start
print('本次運(yùn)行耗時(shí)%.02f' %(run_time))
運(yùn)行結(jié)果如下:

PS:我們的 Excel 表一般是附帶表頭的,合并的時(shí)候是從某行開始,例如,我們需要從第二行開始時(shí),只需改為 pd.read_excel(filelist[i])[1:] ,注意 0 才是第一行, 1 是第二行。
這個(gè)操作優(yōu)點(diǎn)是簡(jiǎn)單易懂,學(xué)幾天 Python 就可以搞的定( Python 上手確實(shí)太太太容易了),適用于表格行數(shù)比較少的情況;缺點(diǎn)是比較耗時(shí),如果行數(shù)比較多(比如我使用的是 5W 行),上個(gè)廁所回來還沒運(yùn)行完。
解法2
Python多進(jìn)程操作
歲月雖漫長(zhǎng),但也耐不住時(shí)光如梭,多快好省才是硬道理。
程序要做的是兩件事兒:(1)打開文件;(2)將打開的文件合并在一起。我們先運(yùn)行一小段代碼測(cè)試下這兩個(gè)功能各自的時(shí)耗。
import time
import pandas as pd
start = time.time()
df1 = pd.read_excel(r'c:/python/aSourseFiles/bi/bi (1).xlsx')
df2 = pd.read_excel(r'c:/python/aSourseFiles/bi/bi (2).xlsx')
df3 = pd.read_excel(r'c:/python/aSourseFiles/bi/bi (3).xlsx')
median = time.time()
df = pd.concat([df1, df2, df3])
end = time.time()
use1 = median - start #計(jì)算打開文件耗時(shí)
use2 = end - median #計(jì)算合并表格耗時(shí)
print(use1)
print(use2)
運(yùn)行結(jié)果如下:

分析發(fā)現(xiàn),時(shí)間主要浪費(fèi)在打開文件上了,因此用多進(jìn)程一次多打開幾個(gè),理論上來說是可以節(jié)省時(shí)間的,說干就干:
import pandas as pd
import time
from multiprocessing import Pool
filelist = ['c:/python/aSourseFiles/bi/bi (' + str(i+1) + ').xlsx' for i in range(40)]
def read_excel(path):
temp = pd.read_excel(path)
print('running')
return temp
def merge_excel(temp):
global df
df = pd.concat([df, temp])
if __name__ == '__main__':
start = time.time()
df = pd.read_excel(filelist[-1]) #以最后一個(gè)文件為基礎(chǔ)進(jìn)行合并操作
p1 = Pool(8) #生成8個(gè)進(jìn)程
for i in range(39):
p1.apply_async(read_excel, args=(filelist[i],), callback=merge_excel) #將打開文件的任務(wù)放入到進(jìn)程中,完成任務(wù)時(shí)回調(diào)merge_excel進(jìn)行合并
p1.close()
p1.join()
print(df.shape)
end = time.time()
run_time = end - start
print('本次運(yùn)行耗時(shí)%.02f' %(run_time))
運(yùn)行結(jié)果如下:

果然是比之前快了些,上個(gè)廁所回來就可以拿到結(jié)果了。
拓展
這段代碼依舊是有點(diǎn)雞肋。40 個(gè)excel,每個(gè) 5W 行,合計(jì) 200W 行,合并完再放進(jìn) Excel 中就不大現(xiàn)實(shí)了。這個(gè)時(shí)候,我們可以通過把數(shù)據(jù)放入到數(shù)據(jù)庫(kù)中進(jìn)行解決,有興趣的小伙伴可以自己嘗試下。
