簡體   English   中英

從python中的隨機行開始讀取CSV文件

[英]Reading CSV files starting from a random line in python

我必須從包含26,00,000行和4列的csv文件(692 MB)中讀取10,000,000行,這些線程在多個線程中,每個線程都從隨機行開始,而當我達到100萬行時停止

我的嘗試:

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()

但是結果是,這些行並不是從隨機開始的,而是每次都從第一行本身開始的。

結果

['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']

嚴格要求我每次都要從隨機行開始

這將在沒有多處理的情況下滿足您的要求,部分原因是您很可能不需要它。

一個簡單的基准使選擇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模塊時從任意點開始嘗試解決此問題,也沒有意義。

讓您可以通過做播種開始在字節與點讀從0字節文件的事實f.seek(start_byte)然后讀取的字節塊在文件中f.read(my_chunk_size) 在這種情況下,要獲得新的一行,您將必須在隨機起始點之后通過new_line_char自行查找行,對行進行自己的解析器,並保持計數器已讀取的行數。

選項2:如果您的文件小於1GB,則說明了這一點。 在計算機上安裝numpy,一口氣讀取文件。 通過索引完整的行集來選擇1e6行。 下面將具有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:我對線路緩存有點好奇,因此我也為此提出了一個解決方案。 更新了正確的發電機設置。

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):

具有350萬行,起始行1M,2M,3M並讀取0.5M行的csv。 為了使它與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
=====================================

您是否曾嘗試在運行隨機數生成器之前為其設置種子? 用這樣的代碼:

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

在生成任何隨機數之前將其添加

據我了解:

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

這是給您隨機行並將其存儲。

在for循環中,您將立即用csvfile的第一行替換此“行”變量。

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

這導致您丟失先前設置的隨機線。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM