如何从大文本文件中删除停用词?

时间:2010-10-31 21:19:10

标签: perl stop-words

我有一个十亿字的语料库,我用标量收集了它。我有一个.regex文件,其中包含我想从我的数据(文本)中消除的所有停用词。

我不知道如何使用这个.regex文件,所以我创建了一个数组并将.regex文件的所有停用词存储在我的停用词数组中。

要删除停用词,我会执行以下操作:

grep { $scalarText =~ s/\b\Q$_\E\b/ /g } @stopList;

这需要很长时间才能执行。如何在Perl脚本中使用.regex文件来删除停用词?或者有没有更快的方法来删除停用词?

3 个答案:

答案 0 :(得分:5)

是的,我想你在那里做的事情非常缓慢,尽管有几个原因。我认为你需要在之前处理你的停用词正则表达式你从你的语料库中建立了十亿字的字符串。

我不知道.regex文件是什么,但是我假设它包含一个合法的Perl正则表达式,你可以使用不超过以下内容编译的东西:

$stopword_string = `cat foo.regex`;
$stopword_rx     = qr/$stopword_string/;

这可能假设一开始就有(?x)

但是如果你的停用词文件是一个行列表,你需要做更多这样的事情:

chomp(@stopwords = `cat foo.regex`);

# if each stopword is an independent regex:
$stopword_string = join "|" => @stopwords;

# else if each stopword is a literal
$stopword_string = join "|" => map {quotemeta} @stopwords;

# now compile it (maybe add some qr//OPTS)
$stopword_rx     = qr/\b(?:$stopword_string)\b/;

警告

非常小心\b:如果第一个单词中的第一个字符和最后一个单词中的最后一个字符是alphanumunder,它只会按照您的想法执行上述操作(一个\w字符)。否则,它会断言你可能并不意味着什么。如果这可能是一种可能性,那么您需要更加具体。领先\b需要成为(?:(?<=\A)|(?<=\s)),而结尾\b需要成为(?=\s|\z)。这就是大多数人认为 \b的意思,但事实并非如此。

完成此操作后,您应该在阅读时将停用词正则表达式应用于语料库。最好的方法是将内容放入字符串中你只需要稍后拿出来。

所以不要做

$corpus_text = `cat some-giant-file`;
$corpus_text =~ s/$stopword_rx//g;

取而代之的是

my $corpus_path = "/some/path/goes/here";
open(my $corpus_fh, "< :encoding(UTF-8)", $corpus_path)
    || die "$0: couldn't open $corpus_path: $!";

my $corpus_text = q##;

while (<$corpus_fh>) {
    chomp;  # or not
    $corpus_text .= $_ unless /$stopword_rx/;
}

close($corpus_fh)
    || die "$0: couldn't close $corpus_path: $!";

这比将东西放在那里要快得多,以后你只需要再次清理。

我对cat的使用仅仅是一种捷径。我不希望你实际上调用一个程序,至少是所有cat,只是为了读取一个文件,未处理和不受干扰。 ☺

答案 1 :(得分:2)

您可能希望使用Regexp::Assemble将Perl正则表达式列表编译为一个正则表达式。

答案 2 :(得分:0)

我发现了一种更快捷的方法。我节省了大约4秒钟。

my $qrstring = '\b(' . (join '|', @stopList) . ')\b';
$scalarText =~ s/$qrstring/ /g;

其中stopList是我所有单词的数组 scalarText是我的全文。

任何人都可以告诉我一个更快的方法吗?