Perl 如何对文件的内容进行随机抽样?

Perl 如何对文件的内容进行随机抽样?,perl,file,random,sample,Perl,File,Random,Sample,我有一个包含内容的文件 abc def high lmn ... ... 文件中有200多万行。 我想从文件中随机采样行并输出50K行。对如何解决这个问题有什么想法吗?我一直在考虑Perl及其rand函数(或者一个方便的shell命令就可以了) 相关(可能重复)问题: 假设您基本上希望输出所有线路的2.5%左右,则可以: print if 0.025 > rand while <$input>; 如果0.025>随机,则打印; 外壳方式: sort -R file |

我有一个包含内容的文件

abc
def
high
lmn
...
...
文件中有200多万行。 我想从文件中随机采样行并输出50K行。对如何解决这个问题有什么想法吗?我一直在考虑Perl及其
rand
函数(或者一个方便的shell命令就可以了)

相关(可能重复)问题:


假设您基本上希望输出所有线路的2.5%左右,则可以:

print if 0.025 > rand while <$input>;
如果0.025>随机,则打印;
外壳方式:

sort -R file | head -n 50000

如果需要提取精确的行数:

use strict;
use warnings;

# Number of lines to pick and file to pick from
# Error checking omitted!
my ($pick, $file) = @ARGV;

open(my $fh, '<', $file)
    or die "Can't read file '$file' [$!]\n";

# count lines in file
my ($lines, $buffer);
while (sysread $fh, $buffer, 4096) {
    $lines += ($buffer =~ tr/\n//);
}

# limit number of lines to pick to number of lines in file
$pick = $lines if $pick > $lines;

# build list of N lines to pick, use a hash to prevent picking the
# same line multiple times
my %picked;
for (1 .. $pick) {
    my $n = int(rand($lines)) + 1;
    redo if $picked{$n}++
}

# loop over file extracting selected lines
seek($fh, 0, 0);
while (<$fh>) {
    print if $picked{$.};
}
close $fh;
使用严格;
使用警告;
#要拾取的行数和要从中拾取的文件数
#忽略错误检查!
我的($pick,$file)=@ARGV;
打开(我的$fh,Perl方式:

使用CPAN。有一个模块可以完全满足您的需要。

来自


除了将文件加载到数据库或对文件中的行进行预索引之外,您还可以做一些事情

以下是骆驼手册中的水库采样算法:

srand;
rand($.) < 1 && ($line = $_) while <>;

另一种方法是使用Tie::File模块,该模块将整个文件视为一个数组。只需访问一个随机数组元素。

您想要输出的行数是精确的还是算法可以输出大约2.5%的所有行数?如果文件大小不同,您可以通过计算行数来计算百分比(参见perlfaq5)这是一个非常好的解决方案,因为它避免了解决这个问题的幼稚方法,即跳转到文件中的随机点或(甚至更糟!)对输入进行排序。@James Thompson:虽然它看起来是一个不错的解决方案,但实际上并不是问题的正确解决方案。无法保证它将返回50k行。如果您想对大约2.5%的所有行进行采样,我的解决方案是一个非常好的解决方案。如果要求正好输出50行,我的解决方案就不是正确的解决方案,000行。我明确说明了这个问题的近似性质。对于后一个问题,我相信我曾经读过一个单通算法,但我现在记不起来了。Sinan想到的算法叫做水库采样算法。它在这个网站和互联网上的其他地方都有详细介绍。这是哪一种?我的(GNU coreutils 5.93)不支持-R[sinan@kas版本排序(GNU CURUTILS)7.4版权(C)2009免费软件基金会,Inc.=排序-版本排序(GNU CORUTILLS).610真的很好的方法。唯一缺少的是检查$Point Bug:int(RAND($LINE))可以返回0,但$。从1开始。@jermdemo:Argh和
rand
返回的值小于参数,因此它不会选择最后一行。愚蠢的基于1的变量…我添加了一个
+1
来修复这两种边缘情况。下面的答案让我对储层采样进行了很好的描述,并提供了一种扩展Camel Book代码的简单方法om一行到
k
项目:
use File::Random qw/random_line/;
my $line = random_line($filename);