【问题标题】:Python processing CSV file really slowPython处理CSV文件真的很慢
【发布时间】:2023-04-06 04:13:02
【问题描述】:

所以我试图打开一个 CSV 文件,读取它的字段并在此基础上修复一些其他字段,然后将该数据保存回 csv。我的问题是 CSV 文件有 200 万行。加快速度的最佳方法是什么。
CSV 文件由

ID; DATE(d/m/y); SPECIAL_ID; DAY; MONTH; YEAR

我正在计算具有相同日期的行在我的记录中出现的频率,然后根据该数据更新 SPECIAL_ID。

根据我之前的研究,我决定使用 pandas。我将来会处理更大的数据集(1-2GB)——这个大约 119MB,所以找到一个好的快速解决方案至关重要。

我的代码如下:

df = pd.read_csv(filename, delimiter=';') 
df_fixed= pd.DataFrame(columns=stolpci) #when I process the row in df I append it do df_fixed
d = 31
m = 12
y = 100
s = (y,m,d)
list_dates= np.zeros(s) #3 dimensional array. 
for index, row in df.iterrows():
    # PROCESSING LOGIC GOES HERE
    # IT CONSISTS OF FEW IF STATEMENTS
    list_dates[row.DAY][row.MONTH][row.YEAR] += 1
    row['special_id'] = list_dates[row.DAY][row.MONTH][row.YEAR]
    df_fixed = df_fixed.append(row.to_frame().T)


df_fixed .to_csv(filename_fixed, sep=';', encoding='utf-8')  

我尝试为每处理一千行打印一次。起初,我的脚本需要 3 秒来处理 1000 行,但运行时间越长越慢。
在第 43000 行,它需要 29 秒,依此类推...

感谢所有未来的帮助:)

编辑:
我正在添加有关我的 CSV 和预期输出的其他信息

ID;SPECIAL_ID;sex;age;zone;key;day;month;year
2;13012016505__-;F;1;1001001;1001001_F_1;13;1;2016
3;25122013505__-;F;4;1001001;1001001_F_4;25;12;2013
4;24022012505__-;F;5;1001001;1001001_F_5;24;2;2012
5;09032012505__-;F;5;1001001;1001001_F_5;9;3;2012
6;21082011505__-;F;6;1001001;1001001_F_6;21;8;2011
7;16082011505__-;F;6;1001001;1001001_F_6;16;8;2011
8;21102011505__-;F;6;1001001;1001001_F_6;16;8;2011

我必须将特殊 ID 字段中的 - 替换为适当的数字。
例如对于一行
ID = 2 SPECIAL_ID 将是
26022018505001(
- 被 001 替换)如果 CSV 中的其他人共享相同的 DAY、MONTH、YEAR,__- 将被替换为 002,依此类推...
所以上述行的预期输出将是

ID;SPECIAL_ID;sex;age;zone;key;day;month;year
2;13012016505001;F;1;1001001;1001001_F_1;13;1;2016
3;25122013505001;F;4;1001001;1001001_F_4;25;12;2013
4;24022012505001;F;5;1001001;1001001_F_5;24;2;2012
5;09032012505001;F;5;1001001;1001001_F_5;9;3;2012
6;21082011505001;F;6;1001001;1001001_F_6;21;8;2011
7;16082011505001;F;6;1001001;1001001_F_6;16;8;2011
8;21102011505002;F;6;1001001;1001001_F_6;16;8;2011

编辑:
我将代码更改为如下所示:我用数据填充字典列表,然后将该列表转换为数据框并保存为 csv。这大约需要 30 分钟才能完成

list_popravljeni = []
df = pd.read_csv(filename, delimiter=';')
df_dates = df.groupby(by=['dan_roj', 'mesec_roj', 'leto_roj']).size().reset_index() 
    for index, row in df_dates.iterrows():
        df_candidates= df.loc[(df['dan_roj'] == dan_roj) & (df['mesec_roj'] == mesec_roj) & (df['leto_roj'] == leto_roj) ]
        for index, row in df_candidates.iterrows():
            vrstica = {}
            vrstica['ID'] = row['identifikator']
            vrstica['SPECIAL_ID'] = row['emso'][0:11] + str(index).zfill(2)
            vrstica['day'] = row['day']
            vrstica['MONTH'] = row['MONTH']
            vrstica['YEAR'] = row['YEAR']   
            list_popravljeni.append(vrstica)
    pd.DataFrame(list_popravljeni, columns=list_popravljeni[0].keys())

【问题讨论】:

  • 减少搜索空间的一种方法可能是使用 pandas 切片来替换您的 IF 条件。例如。如果值 > 5 可以切片为 df.loc[df['value']>5,:] 会将您的数据集缩减为仅与您的 if 条件匹配的那些行。这假设您正在寻找一个符合所有条件的结果。
  • 您能否提供一个输入文件的小示例以及在这种情况下的预期输出? DataFrames 没有针对for 循环进行优化,也没有被追加数百万次,但是如果没有一个示例来检查,很难正确地可视化矢量化方法。
  • 我不知道为什么你不能只使用像df = df.groupby(by=['year', 'month', 'day']).size().reset_index() 这样的东西。这将计算特定日期的出现次数。
  • @roganjosh 我做了 :) 检查编辑后的帖子
  • 好的@roganjosh 我按照你的建议尝试了,groupby 工作得很好!我什至不知道熊猫有什么选择。现在我必须将这些数字分配给实际记录..

标签:
python
pandas
csv
numpy