随机选择在Python中占用了太多内存

时间:2017-11-24 15:28:52

标签: python random

我正在尝试选择要从CSV文件中读取的行,选择基于:

n = 123456789    
s = n//10
# skip value will be used with skip_row in pd.read_csv
skip = sorted(random.sample(range(1, n+1), k=(n-s))

由于RAM使用率过高,此行导致脚本崩溃。文件大小接近5 GB,这就是为什么需要随机读取10%的文件。 期望是random.select不会占用太多内存,令人惊讶的是它(最多可达5 GB,甚至更多,如任务管理器所示)

是否有一种有效的方法来选择要跳过的行。

3 个答案:

答案 0 :(得分:0)

感谢所有评论,我设法编写了一个代码,在31秒内找到所有n = 123456789标签/样本(使用Core i5 PC),这里是:

import random 
import time

start_time = time.time()

n=123456789
 if n>123456789:
      step_size = int(1e7)
 else:
      step_size=n//10
no_of_steps = n//step_size-1
s= step_size//10

xx=list(); i=0

while (i<no_of_steps):
     xx= xx + sorted(random.sample(range(i*step_size, (i+1)*step_size-1), k= s))
     i +=1

print("Size of selected samples", len(xx))
print("Percentage achieved", len(xx)/n)
print("Time needed to pick 10% from ", n, "samples is:" , time.time()-start_time)
print("-------- \n Show a few samples", xx[:10], '...', xx[-10:])

答案 1 :(得分:-1)

的确,你目前的方法很重。它真的试图在内存中存储和处理(sample + sort)一个123,456,789个python整数数组。我不相信你实际上需要事先在数组中“跳过”行。如果是这样,您可以使用generator。以下是您可以改为generating样本集的方法:

def random_sampler_generator(input_seq, skip_chance=0.5):
    for i in input_seq:
        if random.random() > skip_chance:
            yield i

for m in random_sampler_generator(xrange(1, n+1), skip_chance=0.1):
    print m

这有点慢,因为它调用random.random()超过1亿次,但由于yield函数,它的内存效率非常高。出于同样的原因,您可能也应该使用xrange代替range

在这里,random_sampler_generator使用启发式抽样方法,因为您不能保证X%,但随着输入集大小的增加,结果会倾向于它。 skip_chance期望浮点数介于0和1之间,其中.1跳过10%,.5跳过50%,.75跳过75%等等。

答案 2 :(得分:-1)

您需要数据的随机子集,但是您抱怨数据太大而无法驻留内存。因此,使用外部排序可以使您的数据达到合适的形状。

source.csv读取所有N个记录,在计数器的PRNG或SHA1之前添加一个随机值,或者(对于唯一记录)每个记录的SHA1,并将N个结果记录发送到{{1或关系数据库中的索引表。

现在您的记录以随机顺序显示在磁盘上,您可以通过读取前S条记录轻松执行第一个实验,而不会影响内存。记住你离开的地方,你可以通过阅读下一个S记录来进行第二次实验。或者,另一种方法是询问第一个S记录,其中初始SHA1 nybble为'3',另一个S记录以'5'开头,依此类推。您的实验设计不必担心在多个实验中随机遇到相同的源记录,因为您创建了非重叠的分区。

编辑:无需替换生成随机索引不同于生成实验数据的随机折叠。请求是为了节省内存。这种方法工作速度很快,内存有限(永远不会与/usr/bin/sort成比例),使用CSV输入指定的OP问题。尾部-4给出了结果,在OP所需的数据大小的前置运行在五分钟(302秒),这种运行大约一分钟(77秒):

s