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]

上記のコードは私が望むものを達成しますが、非常に遅いです。最初の 100 程度の間隔は数分で処理できますが、間隔が経過するたびに指数関数的に遅くなるため、実行には数日かかります。これを行うためのより高速またはより効率的な方法はありますか? 問題は、ファイル全体をスキャンして、ループのたびに指定された間隔内の位置を見つける必要があることだと思います。

4

3 に答える 3

1

時間の経過とともにプログラムの速度が低下する理由は、出力ファイルごとに CSV ファイルを何度も読み直すためです。見ている範囲が CSV ファイルを下に移動するにつれて、すべての出力ファイルに対してますます多くのデータを読み取る必要があります (そのほとんどはスキップします)。したがって、指数関数的にパフォーマンスが低下します。

CSV を 1 回だけ順番に読み取り、ループ内で関心のある範囲を選択する (そしてファイルに書き込む) ように、コードを再編成する必要があります。これは、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

OK、私はこれをあなたのコードの精神に保とうとしました。大きなファイルを1回だけ繰り返します。書き込み中に再結合しただけなので、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 に答える