Как быстрее сравнивать строки в одном CSV-файлеPython

Программы на Python
Anonymous
Как быстрее сравнивать строки в одном CSV-файле

Сообщение Anonymous »

У меня есть CSV-файл, содержащий 720 000 строк и 10 столбцов, столбцы, имеющие отношение к проблеме:

Код: Выделить всё

['timestamp_utc', 'looted_by__name', 'item_id', 'quantity']
Этот файл представляет собой журналы предметов, которые люди грабят с земли в игре. Проблема в том, что иногда в регистраторе лута с земли появляются ошибки и вводятся данные о человеке, который грабит один и тот же предмет дважды за два. разные строки (эти две строки могут быть разделены максимум 5 строками) с небольшой разницей в столбце timestamp_utc, в противном случае ['looted_by__name', 'item_id', 'quantity'] совпадают, и примером этого может быть:

Код: Выделить всё

2024-06-23T11:40:43.2187312Z,Georgeeto,T4_SOUL,2
2024-06-23T11:40:43.4588316Z,Georgeeto,T4_SOUL,2
где в этом примере 2024-06-23T11:40:43.2187312Z будет меткой времени_utc, 'Georgeeto' будет looted_by__name, T4_SOUL будет идентификатором item_id, а 2 будет количеством.
Что я пытаюсь сделать здесь нужно посмотреть, равны ли ['looted_by__name', 'item_id', 'quantity'] в обеих строках, и если они вычитают метки времени обеих строк друг из друга, и если оно меньше 0,5 секунды, я копирую обе поврежденные строки в файл Corrupted.csv и только одну строку в файл Clean.csv
Я сделал это следующим образом: подписка

Код: Выделить всё

import pandas as pd
import time
from datetime import datetime

start_time = time.time()
combined_df_3 = pd.read_csv("Processing/combined_file_refined.csv", delimiter= ',', usecols=['timestamp_utc', 'looted_by__name', 'item_id', 'quantity'])
combined_df_4 = pd.read_csv("Processing/combined_file_refined.csv", delimiter= ',', usecols=['timestamp_utc', 'looted_by__name', 'item_id', 'quantity'])
bugged_item_df = pd.DataFrame()
clean_item_df = pd.DataFrame()

bugged_item_list = []
clean_item_list = []

date_format = '%Y-%m-%dT%H:%M:%S.%f'

for index1,row1 in combined_df_3.iterrows():
n = 0
time_stamp_1 = datetime.strptime(row1['timestamp_utc'][:26], date_format)
name_1 = row1['looted_by__name']
item_id_1 = row1['item_id']
quantity_1 = row1['quantity']

for index2, row2 in combined_df_4.iterrows():
print(str(n))
n += 1
if n > 5:
break

time_stamp_2 = datetime.strptime(row2['timestamp_utc'][:26], date_format)
name_2 = row2['looted_by__name']
item_id_2 = row2['item_id']
quantity_2 = row2['quantity']

if time_stamp_1 == time_stamp_2 and name_1 == name_2 and item_id_1 == item_id_2 and quantity_2 == quantity_2:
break # get out of for loop here

elif name_1 == name_2 and item_id_1 == item_id_2 and quantity_1 == quantity_2:
if time_stamp_1 > time_stamp_2:
date_diff = abs(time_stamp_1 - time_stamp_2)
date_diff_sec = date_diff.total_seconds()

elif time_stamp_1 < time_stamp_2:
date_diff = abs(time_stamp_2 - time_stamp_1)
date_diff_sec = date_diff.total_seconds()

if date_diff_sec < 0.5:
bugged_item_df = bugged_item_df._append(row1 ,ignore_index=True)
bugged_item_df = bugged_item_df._append(row2 ,ignore_index=True) #add both lines into  a csv file and not write 1 of them into the final csv file

elif date_diff_sec >  0.5:
pass # type line into a csv file normally
else:
pass # type line into a csv file normally

bugged_item_df.to_csv("test.csv", index=False)
clean_item_df.to_csv('test2.csv', index=False)

end_time = time.time()
execution_time = end_time - start_time

print(f"Execution time: {execution_time} seconds")
То, как я это делаю «Технически», работает, но на то, чтобы перебросить весь файл, уходит около 6–13 часов.
Я пришел спросить, есть ли способ его оптимизировать чтобы работать быстрее
примечание: код еще не закончен, но вы можете почерпнуть из него идею
обновление: благодаря совету AKZ (я люблю тебя, чувак) мне удалось сократить время с 13,4 часа до 32 минут, и я понял, что опубликованный мной код также был выполнен неправильно в цикле for, поэтому я дал следующий ответ

Код: Выделить всё

import time
import pandas as pd
from datetime import datetime

#orgnizing the rows
df = pd.read_csv("processing/combined_file_refined.csv", delimiter= ',', usecols=['timestamp_utc', 'looted_by__name', 'item_id', 'quantity'])
df = df.groupby(['looted_by__name', 'timestamp_utc']).sum().reset_index()
df.to_csv("test.csv", index=False)

bugged_item_df = pd.DataFrame()
clean_item_df = pd.DataFrame()
df1 =pd.read_csv("test.csv", delimiter= ',', usecols=['timestamp_utc', 'looted_by__name', 'item_id', 'quantity'])
date_format = '%Y-%m-%dT%H:%M:%S.%f'
n = 0
num_of_runs = 0

start_time = time.time()

for index1,row1 in df.iterrows():
num_of_runs += 1
n += 1
try:
row2 = df1.iloc[n]
except IndexError:
clean_item_df = clean_item_df._append(row1 ,ignore_index=True)
break
time_stamp_1 = datetime.strptime(row1['timestamp_utc'][:26], date_format)
name_1 = row1['looted_by__name']
item_id_1 = row1['item_id']
quantity_1 = row1['quantity']

time_stamp_2 = datetime.strptime(row2['timestamp_utc'][:26], date_format)
name_2 = row2['looted_by__name']
item_id_2 = row2['item_id']
quantity_2 = row2['quantity']

if name_1 != name_2 or item_id_1 != item_id_2 or quantity_1 != quantity_2:
#add row 1 to df
continue
elif time_stamp_1 > time_stamp_2:
date_diff_1 = abs(time_stamp_1 - time_stamp_2)
date_diff_sec_1 = date_diff_1.total_seconds()
if date_diff_sec_1 < 0.5:
#donot add row 1 to df and add row 1 and row 2 to bugged item list
bugged_item_df = bugged_item_df._append(row1 ,ignore_index=True)
bugged_item_df = bugged_item_df._append(row2 ,ignore_index=True)
pass
elif date_diff_sec_1 > 0.5:
clean_item_df = clean_item_df._append(row1 ,ignore_index=True)
#add row 1 to df
continue

elif time_stamp_1 < time_stamp_2:
date_diff_2 = abs(time_stamp_2 - time_stamp_1)
date_diff_sec_2 = date_diff_2.total_seconds()
if date_diff_sec_2 < 0.5:
bugged_item_df = bugged_item_df._append(row1 ,ignore_index=True)
bugged_item_df = bugged_item_df._append(row2 ,ignore_index=True)
#donot add row 1 to df and add row 1 and row 2 to bugged item list
pass
elif date_diff_sec_2 >  0.5:
clean_item_df = clean_item_df._append(row1 ,ignore_index=True)
#add row 1 to df
continue

bugged_item_df.to_csv("bugged.csv", index=False)
clean_item_df.to_csv("clean.csv", index=False)

end_time = time.time()
execution_time = end_time - start_time
print(f"Execution time: {execution_time} seconds")
если у кого-то есть ответ лучше, чем тот, который я дал, опубликуйте его, я буду очень признателен.
обновление 2:
я отредактировал снова набрал код и понял, что могу просто удалить ошибочные строки быстрее, теперь это делается за 60 секунд

Код: Выделить всё

import time
import pandas as pd
from datetime import datetime

#orgnizing the rows
combined_df_3 = pd.read_csv("processing/combined_file_refined.csv", delimiter= ',', usecols=['timestamp_utc', 'looted_by__name', 'item_id', 'quantity'])
combined_df_3 = combined_df_3.groupby(['looted_by__name', 'timestamp_utc']).sum().reset_index()
combined_df_3.to_csv("processing/combined_file_orgnized.csv", index=False)

bugged_item_df = pd.DataFrame()
bugged_item_2df = pd.DataFrame()
combined_df_4 =pd.read_csv("processing/combined_file_orgnized.csv", delimiter= ',', usecols=['timestamp_utc', 'looted_by__name', 'item_id', 'quantity'])
date_format = '%Y-%m-%dT%H:%M:%S.%f'
num_of_runs = 0

for index1,row1 in combined_df_3.iterrows():
num_of_runs += 1
try:
row2 = combined_df_4.iloc[num_of_runs]
except IndexError:
break
time_stamp_1 = datetime.strptime(row1['timestamp_utc'][:26], date_format)
name_1 = row1['looted_by__name']
item_id_1 = row1['item_id']
quantity_1 = row1['quantity']

time_stamp_2 = datetime.strptime(row2['timestamp_utc'][:26], date_format)
name_2 = row2['looted_by__name']
item_id_2 = row2['item_id']
quantity_2 = row2['quantity']

if name_1 != name_2 or item_id_1 != item_id_2 or quantity_1 != quantity_2:
continue
elif time_stamp_1 > time_stamp_2:
date_diff_1 = abs(time_stamp_1 - time_stamp_2)
date_diff_sec_1 = date_diff_1.total_seconds()
if date_diff_sec_1 < 0.5:
#donot add row 1 to df and add row 1 and row 2 to bugged item list
bugged_item_df = bugged_item_df._append(row1 ,ignore_index=True)
bugged_item_df = bugged_item_df._append(row2 ,ignore_index=True)
bugged_item_2df = bugged_item_2df._append(row1,ignore_index=True)

elif time_stamp_1 < time_stamp_2:
date_diff_2 = abs(time_stamp_2 - time_stamp_1)
date_diff_sec_2 = date_diff_2.total_seconds()
if date_diff_sec_2 < 0.5:
bugged_item_df = bugged_item_df._append(row1 ,ignore_index=True)
bugged_item_df = bugged_item_df._append(row2 ,ignore_index=True)
bugged_item_2df = bugged_item_2df._append(row1,ignore_index=True)
#donot add row 1 to df and add row 1 and row 2 to bugged item list

bugged_item_df.to_csv("bugged.csv", index=False)
print('here')
clean_item_df = combined_df_3.merge(bugged_item_2df, on=['timestamp_utc', 'looted_by__name', 'item_id', 'quantity'], how='left', indicator=True).query('_merge == "left_only"').drop('_merge', axis=1)
clean_item_df.to_csv("clean.csv", index=False)
Если кто-то знает, как улучшить его за пределами 30 секунд, не стесняйтесь добавить другой способ

Подробнее здесь: https://stackoverflow.com/questions/787 ... ile-faster

Вернуться в «Python»