Last night i was developing a python code that compares a Excel (4 columns, 30 thousand lines) to another Excel (4 columns, 30 thousand lines), generating another Excel with the differences found. The structure is very similar to the code following this text, firstly, it finds an specific product in the other excel, and them compares their attributes. It works really well, the problem is: it takes 80 hours to run this code, and i need to run in no longer than 2. This example below is a simple version of the real code, the real one deals with XLSX with 30 thousand rows and more than 90 columns. How can i make it quicker?
#imports
from datetime import date
import pandas as pd
import xlsxwriter
#reading XLS's
tabelac = pd.read_excel('TESTE.xlsx', 'Dados')
tabelae = pd.read_excel('TESTE2.xlsx', 'Dados')
#Excluding Nan Values
print(len(tabelac))
for i in range(len(tabelac)):
produto = tabelac.loc[i,'Produto']
if pd.isna(produto):
tabelac.loc[i,'Produto'] = ''
preco = tabelac.loc[i,'Preço']
if pd.isna(preco):
tabelac.loc[i,'Preço'] = ''
tipo = tabelac.loc[i,'Tipo']
if pd.isna(tipo):
tabelac.loc[i,'Tipo'] = ''
Q_vendas = tabelac.loc[i,'Q_vendas']
if pd.isna(Q_vendas):
tabelac.loc[i,'Q_vendas'] = ''
for i in range(len(tabelae)):
produto = tabelae.loc[i,'Produto']
if pd.isna(produto):
tabelae.loc[i,'Produto'] = ''
preco = tabelae.loc[i,'Preço']
if pd.isna(preco):
tabelae.loc[i,'Preço'] = ''
tipo = tabelae.loc[i,'Tipo']
if pd.isna(tipo):
tabelae.loc[i,'Tipo'] = ''
Q_vendas = tabelae.loc[i,'Q_vendas']
if pd.isna(Q_vendas):
tabelae.loc[i,'Q_vendas'] = ''
#printing XLS's
print(tabelac)
print()
print('--------------------------')
print()
print(tabelae)
#declaring error list
erros = []
#evaluating errors
for i in range(len(tabelac)):
for e in range(len(tabelae)):
if tabelac.loc[i,'Produto'] == tabelae.loc[e,'Produto']:
if tabelac.loc[i,'Preço'] != tabelae.loc[e,'Preço']:
erros.append(f'Divergência no Preço do produto {tabelac.loc[i,"Produto"]}')
if tabelac.loc[i,'Tipo'] != tabelae.loc[e,'Tipo']:
erros.append(f'Divergência Tipo do produto {tabelac.loc[i,"Produto"]}')
if tabelac.loc[i,'Q_vendas'] != tabelae.loc[e,'Q_vendas']:
erros.append(f'Divergência preço do produto {tabelac.loc[i,"Produto"]}')
#evaluating missing products
for i in range(len(tabelac)):
for e in range(len(tabelae)):
if tabelac.loc[i,'Produto'] == tabelae.loc[e,'Produto']:
break
if tabelac.loc[i,'Produto'] != tabelae.loc[e,'Produto'] and (e+1) == len(tabelae):
erros.append(f'O produto {tabelac.loc[i,"Produto"]} não foi encontrado em ambas as tabelas')
for i in range(len(tabelae)):
for e in range(len(tabelac)):
if tabelae.loc[i,'Produto'] == tabelac.loc[e,'Produto']:
break
if tabelae.loc[i,'Produto'] != tabelac.loc[e,'Produto'] and (e+1) == len(tabelac):
erros.append(f'O produto {tabelae.loc[i,"Produto"]} não foi encontrado em ambas as tabelas')
#printing results to compare with XLSX
for i in range(len(erros)):
print()
print(erros[i])
#generating the XLS's to exhibit values obtained
workbook = xlsxwriter.Workbook('Results.xlsx')
worksheet = workbook.add_worksheet()
row = 3
column = 0
data_atual = date.today()
data_em_texto = '{}/{}/{}'.format(data_atual.day, data_atual.month,data_atual.year)
worksheet.write(0, 0, f'XLS generated in {data_em_texto}')
worksheet.write(1, 0, '')
worksheet.write(2, 0, 'Errors Found')
for item in erros:
# write operation perform
worksheet.write(row, column, item)
# incrementing the value of row by one
row += 1
workbook.close()
If I were supposed to compare the first XLSX with 4 lists(Products, Type, Price, Sales Amount), is there a better method to perform this task?
4x30k rows is a small file.
As pointed multiple times in StackOverflow, do not loop over rows, pandas is prepared to operate matrix-wise . In your case you not only you have row iteration but nested for which builds to N² time.
For instance, .fillna
is orders of magnitude faster than for
+ isna
You have multiple ways to proceed, merge
on='Produto'
is likely a good candidate:
how='outer'
Will create a 30x4..8 columns. Columns will have _x
on the first file, _y
on the second one From there, you can see if _x
and _y
have data and extract the if product is in A, in B, or in both
Edit: proof of concept example (not tested)
tabelac = pd.read_excel('TESTE.xlsx', 'Dados')
tabelae = pd.read_excel('TESTE2.xlsx', 'Dados')
merged = tabelac.merge(tabelae, how='outer', left_on='Produto', right_on='Produto')
wrong_price = merged['Preço_x']!=merged['Preço_y']
wrong_type = merged['Tipo_x']!=merged['Tipo_y']
# (...and so on)
print(f"Products with wrong price: {merged[wrong_price]}")
# To dump the full table at once:
merged[wrong_price].to_excel('items_with_wrong_price.xlsx')
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.