Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/29.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么python中的文件处理会花费更多的时间来处理文件后面的块?_Python - Fatal编程技术网

为什么python中的文件处理会花费更多的时间来处理文件后面的块?

为什么python中的文件处理会花费更多的时间来处理文件后面的块?,python,Python,我有一个解析JSON文件的非常简单的代码。该文件包含作为JSON对象的每一行。由于某种原因,每行的处理时间随着代码的运行而增加 有人能给我解释一下为什么会发生这种情况以及如何阻止这种情况吗 以下是代码片段: from ast import literal_eval as le import re import string from pandas import DataFrame import pandas import time f = open('file.json') df = DataF

我有一个解析JSON文件的非常简单的代码。该文件包含作为JSON对象的每一行。由于某种原因,每行的处理时间随着代码的运行而增加

有人能给我解释一下为什么会发生这种情况以及如何阻止这种情况吗

以下是代码片段:

from ast import literal_eval as le
import re
import string
from pandas import DataFrame
import pandas
import time
f = open('file.json')
df = DataFrame(columns=(column_names))
row_num = 0
while True:
    t = time.time()
    for line in f:
        line = line.strip()
        d = le(line)
        df.loc[row_num] = [d[column_name1], d[column_name2]]
        row_num+=1
        if(row_num%5000 == 0):
            print row_num, 'done', time.time() - t
            break
df.to_csv('MetaAnalysis', encoding='utf-8')
部分输出如下:

5000 done 11.4549999237     
10000 done 16.5380001068    
15000 done 24.2339999676    
20000 done 36.3680000305    
25000 done 50.0610001087    
30000 done 57.0130000114    
35000 done 65.9800000191    
40000 done 74.4649999142 

可见,每行的时间都在增加。

通过在行中插入新元素,单调地增加数据结构df.loc

df.loc[row_num] = [d[column_name1], d[column_name2]].

变量df.loc似乎是一个字典(例如)。在python字典中插入的元素越多,插入的速度就越慢。这一点已在本节中讨论过。因此,不断增加的字典大小最终会减慢循环的内部代码。

因此,根据mayercn的回答和Hugh Bowell的评论,我能够识别代码的问题。 我修改代码如下,将时间减少了1/12(平均值)。 TL;DR:我将行附加到列表中,然后将其附加到最终的数据帧中

from ast import literal_eval as le
import re
import string
from pandas import DataFrame
import pandas
import time
f = open('Filename')
df = DataFrame(columns=cols)
row_num = 0
while True:
    t = time.time()
    l = []
    for line in f:
        line = line.strip()
        bug = le(line)
        l.append([values])
        row_num+=1
        if(row_num%5000 == 0):
            print row_num, 'done', time.time() - t
            df = df.append(pandas.DataFrame(l),ignore_index=True)
            break
df.to_csv('File', index='id', encoding='utf-8')
输出时间:

5000 done 0.998000144958
10000 done 1.01800012589
15000 done 1.01699995995
20000 done 0.999000072479
25000 done 1.04600000381
30000 done 1.09200000763
35000 done 1.06200003624
40000 done 1.14300012589
45000 done 1.00900006294
50000 done 1.06600022316

Pandas在追加行方面的速度是出了名的慢——它在数据上维护层次索引,并且每次追加一行时都必须更新所有索引

这意味着添加一千行(然后更新)比添加一千行(然后更新)快得多

要遵循的示例代码;我还在下载

编辑:显然,我下载并提取的文件(
/dump/mozilla/mozall.bson
,890 MB)是bson中的MongoDB转储文件,具有TenGen扩展名,包含769k行。出于测试目的,我获取了前50k行并重新保存为json(结果是54MB,平均行数约为1200个字符),然后使用Notepad++将其拆分为每行一条记录

这里的大部分复杂性都是为了分块读取文件:

from itertools import islice
import pandas as pd
from time import time

LINES_PER_BLOCK = 5000

# read object chunks from json file
with open("mozilla.json") as inf:
    chunks = []
    while True:
        start = time()
        block = list(islice(inf, LINES_PER_BLOCK))
        if not block:
            # reached EOF
            break
        json  = "[" + ",".join(block) + "]"
        chunk = pd.read_json(json, "records")
        chunks.append(chunk)
        done = time()
        print(LINES_PER_BLOCK * len(chunks), "done", done - start)
        start = done

# now combine chunks
start = time()
df = pd.concat(chunks)
done = time()
print("Concat done", done - start)

5000 done 0.12293195724487305
10000 done 0.12034845352172852
15000 done 0.12239885330200195
20000 done 0.11942410469055176
25000 done 0.12282919883728027
30000 done 0.11931681632995605
35000 done 0.1278700828552246
40000 done 0.12238287925720215
45000 done 0.12096738815307617
50000 done 0.20111417770385742
Concat done 0.04361534118652344
Total time 1.247551441192627
总时间为1.355s;如果不需要对文件进行分块,它可以简化为

import pandas as pd
from time import time

start = time()

with open("mozilla.json") as inf:
    json = "[" + ",".join(inf) + "]"
df = pd.read_json(json, "records")

done = time()
print("Total time", done - start)

5000 done 0.12293195724487305
10000 done 0.12034845352172852
15000 done 0.12239885330200195
20000 done 0.11942410469055176
25000 done 0.12282919883728027
30000 done 0.11931681632995605
35000 done 0.1278700828552246
40000 done 0.12238287925720215
45000 done 0.12096738815307617
50000 done 0.20111417770385742
Concat done 0.04361534118652344
Total time 1.247551441192627

看起来
df.loc
O(n)
WRT
df
中的项目数?其中一种方法是为每个5000块和pd.concat块创建
df
,这可能没有pd.Series和append那么快,但可能比当前的快。您有没有机会共享到MozillaBugs.json的链接?通过使用ie
df,您可能会大大加快加载速度。从_记录中
。我的速度又快了8倍;-)