1

我有一个包含大约 140 万行和 50 列的大型制表符分隔文件。在我对文件中包含的数据做任何事情之前,我想把这个大文件分成大约几千个小文件。我的文件的第一列包含位置信息,我希望每个较小的文件都是基于此信息的特定间隔。在单独的列表中,我有要拆分较大文件的每个间隔的开始和停止。这是执行此操作的代码部分,开始和停止位置包含在名为 start_L 和 stop_L 的列表中:

for i in range(len(id)):
   out1=((file%s.txt)%(id[i]))
   table=open('largefile.tsv',"r")
   start=int(start_L[i])
   stop=int(stop_L[i])
   table.next()
   temp_out=open(out1,"w")
   reader=csv.reader(table,delimiter="\t")
   for line in reader:
       if int(line[0]) in range(start,stop):
           for y in line:
               temp_out.write(("%s\t")%(y))
           temp_out.write("\n")
    else:
        if int(line[0]) > stop:
            break
        else:
            pass
print "temporary file..." , id[i]

上面的代码实现了我想要的,但是非常慢。它可以在几分钟内处理前一百个左右的时间间隔,但随着每个时间间隔的过去,它会以指数方式变慢,因此需要几天时间才能运行。有没有更快或更有效的方法来做到这一点?我认为问题在于它必须扫描整个文件以在每次循环中找到指定间隔内的位置。

4

3 回答 3

1

您的程序随着时间的推移变慢的原因是因为您为每个输出文件一遍又一遍地重新读取 CSV 文件。随着您查看的范围在 CSV 文件中向下移动,您需要为每个输出文件读取越来越多的数据(其中大部分您会跳过)。因此,性能呈指数下降。

您需要重新组织您的代码,以便您仅按顺序读取 CSV 一次,并在循环中挑选出感兴趣的范围(并将它们写入文件)。仅当 CSV 按范围排序(您说是)并且您的 start_L/stop_L 也相应地排序时,这才有可能。

于 2013-02-07T18:36:14.963 回答
1

在大多数情况下,上面提供的解决方案对我有帮助,但由于我的输入没有 # 行,我不得不进行以下更改。

    table=fileinput.input('largefile.csv',mode="r")
    #
    #
    #
         if fileinput.lineno() >= stop :

我的文件是 | 以大约 600k 行和大约 120MB 大小分隔;整个文件在几秒钟内就被拆分了。

于 2016-01-05T18:53:24.243 回答
0

好的,我试图保持您代码的精神。它只遍历大文件一次,它不需要通过 csv 模块解析行,因为您只是在写入期间重新加入它们。

id=("a","b")
start_L=(1,15)
stop_L=(16,40)

i=0
table=open('largefile.tsv',"r")
out1=(("file%s.txt")%(id[i]))
temp_out=open(out1,"w")

# start iterating through the file 
for line in table:
     stop=int(stop_L[i])

     # Split the line into a position piece, and a 
     # throw away variable based upon the 1st tab char
     position,the_rest= line.split("\t",1)

     # I'm ignoring start as you mentioned it was sorted in the file
     if int(position) >= stop :
           # Close the current file
           temp_out.close()

           # Increment index so file name is pulled from id properly
           # If the index is past the length of the id list then 
           # break otherwise open the new file for writing
           i += 1  
           if (i < len(id)):
             out1=(("file%s.txt")%(id[i]))
             temp_out=open(out1,"w")
           else:
             break 

     temp_out.write(line)

我的测试文件行看起来像

1       1a      b       c       d       e
2       2a      b       c       d       e
3       3a      b       c       d       e

根据您的具体数据,这可以简化很多,但我希望它至少能给您一个开始。

于 2013-02-07T18:59:16.817 回答