Python处理CSV文件的速度非常慢

Python处理CSV文件的速度非常慢,python,pandas,csv,numpy,Python,Pandas,Csv,Numpy,因此,我试图打开一个CSV文件,读取其字段,并根据该文件修复一些其他字段,然后将数据保存回CSV。我的问题是CSV文件有200万行。加快速度的最佳方法是什么。 CSV文件包括 ID; DATE(d/m/y); SPECIAL_ID; DAY; MONTH; YEAR 我正在计算记录中出现日期相同的行的频率,然后根据该数据更新特殊ID 基于我之前的研究,我决定使用熊猫。我将在未来处理更大的数据集(1-2GB)-这一组大约为119MB,因此找到一个好的快速解决方案至关重要 我的代码如下: df =

因此,我试图打开一个CSV文件,读取其字段,并根据该文件修复一些其他字段,然后将数据保存回CSV。我的问题是CSV文件有200万行。加快速度的最佳方法是什么。
CSV文件包括

ID; DATE(d/m/y); SPECIAL_ID; DAY; MONTH; YEAR
我正在计算记录中出现日期相同的行的频率,然后根据该数据更新特殊ID

基于我之前的研究,我决定使用熊猫。我将在未来处理更大的数据集(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')  
我试着每处理1000行打印一次。一开始,我的脚本需要3秒钟才能运行1000行,但运行的时间越长,速度就越慢。 第43000行需要29秒,以此类推

感谢您以后的帮助:)

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

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特殊的\u ID将 26022018505001(-被001取代)如果CSV中的其他人在同一天、同一月、同一年共享,则将被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
编辑: 我把代码改成这样:我用数据填充dict列表,然后将该列表转换为dataframe并另存为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())

我认为这会提供你想要的,并避免循环。它可能更有效(我无法找到避免创建
计数的方法)。但是,它应该比您当前的方法快得多

df['counts'] = df.groupby(['year', 'month', 'day'])['SPECIAL_ID'].cumcount() + 1
df['counts'] = df['counts'].astype(str)
df['counts'] = df['counts'].str.zfill(3)
df['SPECIAL_ID'] = df['SPECIAL_ID'].str.slice(0, -3).str.cat(df['counts'])
我在末尾添加了一条假记录,以确认它是否正确递增:

     SPECIAL_ID sex age     zone          key day month  year counts
0  13012016505001   F   1  1001001  1001001_F_1  13     1  2016    001
1  25122013505001   F   4  1001001  1001001_F_4  25    12  2013    001
2  24022012505001   F   5  1001001  1001001_F_5  24     2  2012    001
3  09032012505001   F   5  1001001  1001001_F_5   9     3  2012    001
4  21082011505001   F   6  1001001  1001001_F_6  21     8  2011    001
5  16082011505001   F   6  1001001  1001001_F_6  16     8  2011    001
6  21102011505002   F   6  1001001  1001001_F_6  16     8  2011    002
7  21102012505003   F   6  1001001  1001001_F_6  16     8  2011    003
如果您想消除
计数
,只需:

df.drop('counts', inplace=True, axis=1)

减少搜索空间的一种方法可能是使用pandas切片来替换IF条件。例如,if value>5可以切片为
df。loc[df['value']>5,:]
将数据集裁剪为仅与if条件匹配的行。这假设您正在寻找一个与所有条件匹配的结果。在这种情况下,您能提供一个输入文件和预期输出的小示例吗?数据帧没有针对
循环进行优化,也没有被追加数百万次,但是如果没有一个例子来检查,很难正确地可视化矢量化方法。我不确定为什么不能使用类似
df=df.groupby(by=['year',month',day'].size().reset_index()
的东西。这将计算特定日期的出现次数。@roganjosh我做了:)检查编辑的postook@roganjosh,我按照您的建议尝试过,groupby工作得很好!我甚至不知道熊猫有什么选择。现在我必须将这些数字分配到实际记录中。首先,感谢您的帮助!是的,计数应该递增。记录#5[SPECIAL_ID]应为16082011505001,记录#6[SPECIAL_ID]应为16082011505002@Kristjan但是它具体地根据
ID
列中的顺序递增?因为我认为,
groupby
会破坏任何初始订单,所以我们需要一些固定的东西来建立这个基础,否则在这个阶段,哪个得到
001
,哪个得到
002
都是任意的,不管谁得到哪个号码。我只需要给定一天的所有记录就可以得到1-len(给定一天的记录)我设法加快了速度。我想大概需要30-40分钟才能完成。。。但还是比我以前的方式好。当我有时间的时候,我会发布我的解决方案作为答案。。。如果你认为更快的方法是可能的,我的耳朵open@Kristjan我已经解决了这个问题。我希望我的方法是以秒为单位,而不是以分钟为单位。太好了,我把你的答案整合到了我的代码中,它工作得非常完美而且非常快!我将来会做很多类似上面提到的工作,所以如果你能给我指出一个好的学习资源,那就太好了。