首页 > 编程问答 >如何更快地比较同一 csv 文件中的行

如何更快地比较同一 csv 文件中的行

时间:2024-07-22 03:37:53浏览次数:7  
标签:python pandas dataframe csv analytics

我有一个 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 将是 'timestamp_utc'

'Georgeeto' 将是 'looted_by__name'

'T4_SOUL' 将是 'item_id'

'2' 将是 'quantity'

我在这里试图做的是看看 ['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("Proccesing/combined_file_refined.csv", delimiter= ',', usecols=['timestamp_utc', 'looted_by__name', 'item_id', 'quantity'])
combined_df_4 = pd.read_csv("Proccesing/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("proccesing/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("proccesing/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("proccesing/combined_file_orgnized.csv", index=False)



bugged_item_df = pd.DataFrame()
bugged_item_2df = pd.DataFrame()
combined_df_4 =pd.read_csv("proccesing/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 秒,请随意添加另一种方法


可以利用 Pandas 的矢量化操作来更快地完成此任务,而不是进行迭代。以下是如何操作:

import pandas as pd

# 读取 CSV 文件
df = pd.read_csv("Proccesing/combined_file_refined.csv", usecols=['timestamp_utc', 'looted_by__name', 'item_id', 'quantity'])

# 将时间戳列转换为 datetime 对象
df['timestamp_utc'] = pd.to_datetime(df['timestamp_utc'])

# 按 'looted_by__name'、'item_id' 和 'quantity' 对 DataFrame 排序
df = df.sort_values(['looted_by__name', 'item_id', 'quantity', 'timestamp_utc'])

# 计算与下一行的时差(按分组)
df['time_diff'] = df.groupby(['looted_by__name', 'item_id', 'quantity'])['timestamp_utc'].diff().dt.total_seconds()

# 查找时间差小于 0.5 秒的行
bugged_rows = df[df['time_diff'] < 0.5]

# 从原始 DataFrame 中删除有问题的行以获取干净的数据
clean_df = df[~df.index.isin(bugged_rows.index)]

# 将有问题的行和干净的行保存到 CSV 文件
bugged_rows.to_csv("Corrupted.csv", index=False)
clean_df.to_csv("Clean.csv", index=False)

此代码首先按相关列对 DataFrame 进行排序。然后,它使用 diff() 函数计算同一组内连续行之间的时差。最后,它根据时差过滤行以识别有问题的行并创建干净的 DataFrame。

此方法应比的迭代方法快得多,尤其是对于大型数据集,因为它利用了 Pandas 的矢量化操作。

标签:python,pandas,dataframe,csv,analytics
From: 78770763

相关文章

  • Python 中的 azure.ai.translation.document - 无法使用当前权限访问源文档位置
    我在使用Python中的azure.ai.translation.document库时遇到问题。我已经在Azure中设置了翻译服务以及带有两个容器的Blob存储。我已使用“用户委托密钥”创建了SAS连接。一种用于源(读取/列表),一种用于目标(写入/列表)。例如我尝试运行Python程序,但源b......
  • 博文标题:探索Python中的元编程:装饰器的魔法
    引言在Python的世界里,装饰器(Decorators)是一种非常强大的特性,它允许程序员在不修改原始函数代码的情况下,为函数添加新的功能。这种机制不仅增强了代码的可读性和可维护性,还提供了高度的灵活性和扩展性。本文将深入探讨装饰器的基本概念、工作原理以及如何利用它们来简化和......
  • 使用Python 和 Selenium 抓取 酷狗 音乐专辑 附源码
    在这篇博客中,我将分享如何使用Python和Selenium抓取酷狗音乐网站上的歌曲信息。我们将使用BeautifulSoup解析HTML内容,并提取歌曲和专辑信息。准备工作首先,我们需要安装一些必要的库:pipinstallrequestsbeautifulsoup4selenium代码实现以下是完整的代码:importosi......
  • 基于Django+Python的网易新闻与评论舆情热点分析平台
    一、引言在信息爆炸的时代,人们每天面对海量的信息流,如何从中筛选出有价值的信息并进行深度分析变得尤为重要。基于Django+Python的网易新闻与评论舆情热点分析平台,旨在为用户提供一个高效的数据分析工具,帮助用户快速理解新闻趋势、情感倾向以及公众对特定事件的看法。通过自......
  • Python解释器详解及其应用场景
    Python解释器及其应用场景一、Python解释器概述Python解释器是Python程序运行的核心,它负责读取Python代码(即.py文件)并将其转换为机器语言,从而使计算机能够执行。简单来说,Python解释器就像是Python代码与计算机之间的翻译官,把Python代码翻译成计算机能懂的语言。Python解释器......
  • 利用【MATLAB】和【Python】进行【图与网络模型】的高级应用与分析】
    目录一、图与网络的基本概念1.无向图与有向图2.简单图、完全图、赋权图3.顶点的度4.子图与连通性5.图的矩阵表示MATLAB代码实例Python代码实例 二、最短路径问题1.最短路径问题的定义2.Dijkstra算法MATLAB代码实例Python代码实例三、最小生成树问题1.......
  • python_wholeweek1
    目录(day1-7)一周的学习1.计算机之编程什么是编程语言什么是编程为什么要编程2.计算机组成原理计算机五大组成CPU控制器运算器内存外存输入设备输出设备(I/O设备)32位和64位32位64位多核CPU硬盘工作原理机械硬盘工作原理固态硬盘工作原理3.计算机操作系统文件是什么?应用程序是什......
  • python模块与包
    python模块与包1.模块(是一个python文件)自定义模块:(1)新建一个py文件在同一个project里然后可以用import先导入再在main里使用main.py importcc.ad(2,5)c.py defad(s,y):print(s+y)导入模块中的方法会自动实行被调用模块里所有所有语句(2)导入不同模块同一方法......
  • Python网络数据可视化全攻略【方法与技巧详解】
    ......
  • Python爬虫实战案例(爬取文字)
    爬取豆瓣电影的数据首先打开"豆瓣电影Top250"这个网页:按F12,找到网络;向上拉动,找到名称栏中的第一个,单机打开;可以在标头里看到请求URL和请求方式,复制URL(需要用到);在表头的最下面有"User-Agent",也复制下来(也可以下载pipinstallfake_useragent库,用别人写好的UA)。定位......