jbs*_*ssm 30 python csv random file
我有这个非常大的CSV文件(15 Gb),我需要读取大约100万条随机行.据我所知 - 并实现 - Python中的CSV实用程序只允许在文件中按顺序迭代.
将所有文件读入内存以使用一些随机选择是非常耗费内存的,并且通过所有文件并丢弃一些值并选择其他文件非常耗时,因此,无论如何都要从CSV文件中选择一些随机行并且只读那行?
我尝试没有成功:
import csv
with open('linear_e_LAN2A_F_0_435keV.csv') as file:
reader = csv.reader(file)
print reader[someRandomInteger]
Run Code Online (Sandbox Code Playgroud)
CSV文件的示例:
331.093,329.735
251.188,249.994
374.468,373.782
295.643,295.159
83.9058,0
380.709,116.221
352.238,351.891
183.809,182.615
257.277,201.302
61.4598,40.7106
Run Code Online (Sandbox Code Playgroud)
Mar*_*ina 27
import random
filesize = 1500 #size of the really big file
offset = random.randrange(filesize)
f = open('really_big_file')
f.seek(offset) #go to random position
f.readline() # discard - bound to be partial line
random_line = f.readline() # bingo!
# extra to handle last/first line edge cases
if len(random_line) == 0: # we have hit the end
f.seek(0)
random_line = f.readline() # so we'll grab the first line instead
Run Code Online (Sandbox Code Playgroud)
正如@AndreBoos指出的那样,这种方法会导致偏向选择.如果您知道线的最小和最大长度,则可以通过执行以下操作来消除此偏差:
让我们假设(在这种情况下)我们有min = 3和max = 15
1)找到前一行的长度(Lp).
然后,如果Lp = 3,则该线最偏向.因此,如果Lp = 15,我们应该100%的时间,这条线最偏向于.我们应该只占20%的时间,因为选择的可能性要高5倍.
我们通过随机保持X%的时间来实现这一点:
X = min/Lp
如果我们不保留这条线,我们会做另一个随机选择,直到我们的骰子卷好.:-)
Sha*_*hin 10
我有这个非常大的CSV文件(15 Gb),我需要读取大约100万条随机行
假设您不需要确切的 100万行,并且事先知道CSV文件中的行数,您可以使用油藏采样来检索随机子集.只需遍历您的数据,每行确定选择行的机会.这样,您只需要传递一次数据.
如果您需要经常提取随机样本但实际数据集不经常更改(因为您每次数据集更改时只需跟踪条目数),这种方法效果很好.
chances_selected = desired_num_results / total_entries
for line in csv.reader(file):
if random() < chances_selected:
result.append(line)
Run Code Online (Sandbox Code Playgroud)
您可以使用概率方法的变体来选择文件中的随机行.
您可以保留大小的缓冲区,而不是只保留一个被选中的数字C.对于每个行号,n在带有N行的文件中,您希望选择具有概率的行C/n(而不是原始行1/n.如果选择了该数,则从C长度缓冲区中选择一个随机位置以逐出.
以下是它的工作原理:
import random
C = 2
fpath = 'somelines.txt'
buffer = []
f = open(fpath, 'r')
for line_num, line in enumerate(f):
n = line_num + 1.0
r = random.random()
if n <= C:
buffer.append(line.strip())
elif r < C/n:
loc = random.randint(0, C-1)
buffer[loc] = line.strip()
Run Code Online (Sandbox Code Playgroud)
这需要单次传递文件(因此它是线性时间)并返回文件中的精确 C行.每条线都有C/N被选中的概率.
为了验证上述是否有效,我创建了一个包含a,b,c,d,e的5行文件.我用C = 2运行代码10,000次.这应该产生5选择2(所以10)可能选择的均匀分布.结果:
a,b: 1046
b,c: 1018
b,e: 1014
a,c: 1003
c,d: 1002
d,e: 1000
c,e: 993
a,e: 992
a,d: 985
b,d: 947
Run Code Online (Sandbox Code Playgroud)
小智 5
如果您想多次抓取随机行(例如,用于机器学习的小批量),并且您不介意扫描一次大文件(而不将其加载到内存中),那么您可以创建一个行索引列表并使用seek 快速抓取线条(基于Maria Zverina 的回答)。
# Overhead:
# Read the line locations into memory once. (If the lines are long,
# this should take substantially less memory than the file itself.)
fname = 'big_file'
s = [0]
linelocs = [s.append(s[0]+len(n)) or s.pop(0) for n in open(fname)]
f = open(fname) # Reopen the file.
# Each subsequent iteration uses only the code below:
# Grab a 1,000,000 line sample
# I sorted these because I assume the seeks are faster that way.
chosen = sorted(random.sample(linelocs, 1000000))
sampleLines = []
for offset in chosen:
f.seek(offset)
sampleLines.append(f.readline())
# Now we can randomize if need be.
random.shuffle(sampleLines)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
21223 次 |
| 最近记录: |