2017-12-02 1 views
0

26,00,000行と4列からなるcsvファイル(692 MB)から10,00,000行を読み込む必要があります。複数のスレッドではそれぞれがランダムから始まりますPythonで無作為な線から始まるCSVファイルを読む

from multiprocessing.pool import ThreadPool as Pool 
import linecache 
import random 
import csv 
from random import randint 
from time import sleep 

csvfile=csv.reader(open('sample.csv')) 


def process_line(l): 
    sleep(randint(0,3)) 
    print (l) 
def get_random_line():  
    lines_to_get=random.randint(0,2600000) 
    line = linecache.getline('sample.csv', lines_to_get) 

    for lines_to_get, line in enumerate(csvfile): 
     print (line) 

     if lines_to_get >= 1000000: 
     break 

    yield (line) 

f = get_random_line() 

t = Pool(processes=3) 

for i in f: 
    t.map(process_line, (i,)) 


t.close() 

しかし結果で、ラインは、それが最初の行自体から毎回起動、ランダムからスタートされていません:。私は100万回線に達する

私の試みを行および停止

結果

['1', '31', '2.5', '1260759144'] 
['1', '1029', '3.0', '1260759179'] 
['1', '1061', '3.0', '1260759182'] 
['1', '1129', '2.0', '1260759185'] 
['1', '1172', '4.0', '1260759205'] 
['1', '1263', '2.0', '1260759151'] 
['1', '1287', '2.0', '1260759187'] 
['1', '1293', '2.0', '1260759148'] 
['1', '1339', '3.5', '1260759125'] 

要件が厳しく、私はランダムなライン毎回

+0

2600万行のファイルの中でランダムに10 x 100万のチャンクを読む必要があるのはなぜですか?ランダムな選択肢を調整するロジックを入れない限り、同じ行を何度も読む確率はかなり高いですし、それはもはやランダムではありません...とにかく、反復子を見て、読み込みプロセスをチョークして、実際にあなたが読んだこと必要。あなたが満足している方法で小さなプロセスを読み込むアルゴリズムを書いて、それが動作することを確認してから、サブプロセスまたはプール内の小さなチャンクリーダーを大量に読み込むことで問題を解決してください。 – ahed87

+0

または依存関係を確認したら、pandasを見てください。同様の問題の定式化の例がここにあります(https://stackoverflow.com/questions/25962114/how-to-read-a-6-gb-csv-file-with-pandas)。 – ahed87

+0

@ ahed87ありがとうございます。しかし、毎回ランダムなチャンクを取得する方法を教えてください。 – Najma

答えて

0

から始める必要があることをあなたがそれを実行する前に乱数ジェネレータをシード試してみましたか?このようなコードを:あなたが最も可能性が高いそれを必要としない一因

import time 
random.seed(time.time()) 

は、任意の乱数生成

+0

申し訳ありませんが、役に立たない – Najma

1

これは、あなたがマルチプロセッシングなしを頼む何をする前にそれを追加します。

シンプルなベンチマークでは、3つの選択肢がありました。

オプション1:

import csv 

import random 

starting_points = [random.randint(0, 5) for i in range(3)] 

read_nbr_of_lines = 2 

for sp in starting_points: 
    print('random starting line: %s'%sp) 
    read_lines = 0 
    with open('large_csv.csv') as cf: 
     lines = csv.reader(cf) 
     for nbr, line in enumerate(lines): 
      if nbr < sp - 1: continue 
      read_lines += 1 
      if read_lines > read_nbr_of_lines: break 
      print(nbr, line) 

おそらくこれは、大量のデータに遅くなることが判明するだろうが、私は本当にさえへのあなたの願いでこれを回避しようとする際にポイントが表示されませんcsv-moduleを使用している間にランダムな点から開始します。

f.seek(start_byte)でバイトの開始点のシードを行い、続いてf.read(my_chunk_size)でファイルのバイトを読み取ることで、バイト0からファイルを読み取ることができます。その場合、新しい行を取得するには、ランダムな開始点の後にnew_line_charを使用して行を見つけなければなりません。行のために独自のパーサを実行し、読み込んだ行の数をカウンタに保持します。

オプション2: ファイルが1GB未満であることが記載されている場合。 numpyをコンピュータにインストールして、一度にファイルを読んでください。 1行6行をすべての行にインデックスを付けて選択します。 以下にはdtype=np.float64があります。整数を保持したい場合は、それを行う方法もあります。そのためには、numpyのドキュメントを勉強することをお勧めします。

import random 
import numpy as np 
mycsv = np.genfromtxt('large_csv.csv', delimiter=',')  
starting_lines = [random.randint(0, 5) for i in range(3)] 
read_nbr_of_lines = 2 

for sl in starting_lines: 
    print('lines %s to %s'%(sl, sl+read_nbr_of_lines-1)) 
    print(mycsv[sl:sl+read_nbr_of_lines]) 

オプション3: 私はlinecacheに少し好奇心旺盛だので、私は同様にそのための一つの解決策を作りました。 適切な発電機セットアップで更新されました。

import linecache as lc 
import csv 
import random 

starting_lines = [random.randint(1, 10) for i in range(3)] 
read_nbr_of_lines = 2 

for sl in starting_lines: 
    iterator = (lc.getline('large_csv.csv', i) for 
       i in range(sl, sl+read_nbr_of_lines)) 
    mycsv = csv.reader(iterator) 
    print('lines %s to %s'%(sl, sl+read_nbr_of_lines-1)) 
    for row in mycsv: 
     print(row) 

単純なベンチマーク(Py36):

CSV 3.5M線するStartLine 1M、2M、3M及び読取0.5M線を有します。 numpyでいくらか公平にするために、他の行はすべての読取り行を浮動小数点のリストに変換する行を持っています。

結果:私の知る限り理解できるよう

===================================== 
random starting line: 1000000 
last_line 1499999 [1.0, 1172.0, 4.0, 1260759205.0] 
random starting line: 2000000 
last_line 2499999 [1.0, 1263.0, 2.0, 1260759151.0] 
random starting line: 3000000 
last_line 3499999 [3499999.0, 1287.0, 2.0, 1260759187.0] 
option 1 timing: 13.678 seconds 
===================================== 
random starting line: 1000000 
last_line 1499999 [ 1.50000000e+06 1.26300000e+03 2.00000000e+00 1.26075915e+09] 
random starting line: 2000000 
last_line 2499999 [ 2.50000000e+06 1.28700000e+03 2.00000000e+00 1.26075919e+09] 
random starting line: 3000000 
last_line 3499999 [ 3.50000000e+06 1.29300000e+03 2.00000000e+00 1.26075915e+09] 
option 2 timing: 23.453 seconds 
===================================== 
lines 1000000 to 1500000 
last_line 1500000 [1500000.0, 1263.0, 2.0, 1260759151.0] 
lines 2000000 to 2500000 
last_line 2500000 [2500000.0, 1287.0, 2.0, 1260759187.0] 
lines 3000000 to 3500000 
last_line 3500000 [3500000.0, 1293.0, 2.0, 1260759148.0] 
option timing: 7.338 seconds 
===================================== 
0

line = linecache.getline('sample.csv', lines_to_get) 

これはあなたにランダムな行を取得し、それを記憶しています。

forループの直後に、この "行"変数をcsvfileの最初の行に置き換えます。

for lines_to_get, line in enumerate(csvfile): 
     print (line) 

これにより、以前に設定したランダムな線が失われています。

関連する問題