Python 3:如何最好地以随机顺序遍历大文件(+100 万行)中的所有行
Python 3: How to best iterate over all lines in a big file (+1 million lines) in a random order
好的,所以我有多个文本文件,每个包含超过 500.000 甚至 1.000.000 行。
目前我在做这样的事情:
import random
def line_function(line):
# Do something with given line
def random_itteration(filepath):
with open(filepath) as f:
lines = f.readlines()
random.shuffle(lines)
for line in lines:
result = line_function(line)
问题是 random.shuffle()
上的 Python Docs 明确指出(重点是我加的):
Note that even for small len(x), the total number of permutations of x
can quickly grow larger than the period of most random number
generators. This implies that most permutations of a long sequence can
never be generated. For example, a sequence of length 2080 is the
largest that can fit within the period of the Mersenne Twister random
number generator.
所以问题是:
使我的设置按预期工作的最快、最有效的方法是什么?
更多信息:
我想将 line_function() 应用于随机行而不是简单地按它们所在的顺序迭代它们是有原因的。还要注意 我非常喜欢每行只处理一次.
最后,不幸的是,预先打乱文本文件或将其分成较小的文件不是一种选择。这不是我要问的。
欢迎任何见解!提前谢谢大家。
在 Python 中执行此 "quickly and efficiently" 会遇到麻烦,但如果必须的话,可以从洗牌算法开始,例如 Fisher-Yates 算法.
一旦你实现了它,加载你的文件,并记录每行开始的字节偏移量。打乱那个数组,打开你的文件,然后遍历你的数组,并从偏移量读取到下一个换行符。
对于像您提议的那样大的数据集,可以合理地预期 lines = f.readlines()
内存压力太大,需要使用偏移量的更复杂但更具可扩展性的解决方案。
为了更有效地重新运行,也许还可以考虑在生成偏移元数据后将其保存下来,这样您就不需要每次都遍历整个文件(或整个文件)。
比起大行,我更愿意对整数列表进行随机播放。
(整数是行列表中行的 index/position)
像这样:
import random
from random import randint
def line_function(line):
# Do something with given line
def random_itteration(filepath):
with open(filepath) as f:
lines = f.readlines()
count = len(lines)
#random_index_list = random.shuffle(list(xrange(count)))
random_index_list = random.sample(range(count+1),count)
for index in random_index_list:
result = line_function(lines[index])
#shuffled_lines = random.shuffle(lines)
#for line in shuffled_lines:
# result = line_function(line)
正如 Mark Dickinson 所说,您引用的文档行对 real-world 代码基本上没有实际意义。它绝对与您的代码没有任何关系。
洗牌是否对所有可能的排列产生真正均匀的随机分布并不重要。重要的是洗牌是否与这样的分布可区分,达到某种可区分性标准。 random.shuffle
在统计上无法区分完全随机洗牌,直至底层 Mersenne Twister 算法的质量,并且它的区分方式与周期无关。
您不需要做任何特别的事情来进行设置 "work as intended"。 random.shuffle
已经有效。
好的,所以我有多个文本文件,每个包含超过 500.000 甚至 1.000.000 行。
目前我在做这样的事情:
import random
def line_function(line):
# Do something with given line
def random_itteration(filepath):
with open(filepath) as f:
lines = f.readlines()
random.shuffle(lines)
for line in lines:
result = line_function(line)
问题是 random.shuffle()
上的 Python Docs 明确指出(重点是我加的):
Note that even for small len(x), the total number of permutations of x can quickly grow larger than the period of most random number generators. This implies that most permutations of a long sequence can never be generated. For example, a sequence of length 2080 is the largest that can fit within the period of the Mersenne Twister random number generator.
所以问题是:
使我的设置按预期工作的最快、最有效的方法是什么?
更多信息:
我想将 line_function() 应用于随机行而不是简单地按它们所在的顺序迭代它们是有原因的。还要注意 我非常喜欢每行只处理一次.
最后,不幸的是,预先打乱文本文件或将其分成较小的文件不是一种选择。这不是我要问的。
欢迎任何见解!提前谢谢大家。
在 Python 中执行此 "quickly and efficiently" 会遇到麻烦,但如果必须的话,可以从洗牌算法开始,例如 Fisher-Yates 算法.
一旦你实现了它,加载你的文件,并记录每行开始的字节偏移量。打乱那个数组,打开你的文件,然后遍历你的数组,并从偏移量读取到下一个换行符。
对于像您提议的那样大的数据集,可以合理地预期 lines = f.readlines()
内存压力太大,需要使用偏移量的更复杂但更具可扩展性的解决方案。
为了更有效地重新运行,也许还可以考虑在生成偏移元数据后将其保存下来,这样您就不需要每次都遍历整个文件(或整个文件)。
比起大行,我更愿意对整数列表进行随机播放。
(整数是行列表中行的 index/position)
像这样:
import random
from random import randint
def line_function(line):
# Do something with given line
def random_itteration(filepath):
with open(filepath) as f:
lines = f.readlines()
count = len(lines)
#random_index_list = random.shuffle(list(xrange(count)))
random_index_list = random.sample(range(count+1),count)
for index in random_index_list:
result = line_function(lines[index])
#shuffled_lines = random.shuffle(lines)
#for line in shuffled_lines:
# result = line_function(line)
正如 Mark Dickinson 所说,您引用的文档行对 real-world 代码基本上没有实际意义。它绝对与您的代码没有任何关系。
洗牌是否对所有可能的排列产生真正均匀的随机分布并不重要。重要的是洗牌是否与这样的分布可区分,达到某种可区分性标准。 random.shuffle
在统计上无法区分完全随机洗牌,直至底层 Mersenne Twister 算法的质量,并且它的区分方式与周期无关。
您不需要做任何特别的事情来进行设置 "work as intended"。 random.shuffle
已经有效。