从python中的随机行开始读取CSV文件

2024-04-27 00:49:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我必须从一个csv文件(692mb)中读取10万行,该文件由26000行和4列组成,在多个线程中,每个线程从一个随机行开始,当我到达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()

但结果是,这些行不是从随机开始的,而是每次都从第一行开始。在

结果

^{pr2}$

严格的要求是每次我都要从一条随机的线开始


Tags: 文件csvtocsvfilefromimportgetline
3条回答

据我所知:

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

这是获取随机线并存储它。在

在for循环中紧接着,您将用csvfile的第一行替换这个“line”变量。在

^{pr2}$

这会导致你失去先前设定的随机线。在

这将在不需要多处理的情况下满足您的要求,部分原因是您很可能不需要它。在

一个简单的基准使方案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,如果您想保留整数,也有一些方法可以做到这一点。为此,我建议研究一下纽比的文献。在

^{pr2}$

选项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.5米线,1米,2米,3米,读数0.5米线。为了使numpy有点公平,其他人有一行代码将所有读取的行转换为一个float列表。在

结果:

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

在生成任何随机数之前添加它

相关问题 更多 >