映射/减少计数的两阶段排序

时间:2017-02-04 02:54:45

标签: python hadoop mrjob

这个python3程序试图使用map / reduce从文本文件中生成单词的频率列表。我想知道如何订购字数,表示为' count'在第二个reducer的yield语句中,最大计数值最后出现。目前,结果的尾部看起来像这样:

"0002"  "wouldn"
"0002"  "wrap"
"0002"  "x"
"0002"  "xxx"
"0002"  "young"
"0002"  "zone"

对于上下文,我将任何单词文本文件传递给python3程序,如下所示:

python MapReduceWordFreqCounter.py book.txt

以下是MapReduceWordFreqCounter.py的代码:

from mrjob.job import MRJob
from mrjob.step import MRStep
import re

# ignore whitespace characters
WORD_REGEXP = re.compile(r"[\w']+")

class MapReduceWordFreqCounter(MRJob):

    def steps(self):
        return [
            MRStep(mapper=self.mapper_get_words,
                   reducer=self.reducer_count_words),
            MRStep(mapper=self.mapper_make_counts_key,
                   reducer = self.reducer_output_words)
        ]

    def mapper_get_words(self, _, line):
        words = WORD_REGEXP.findall(line)
        for word in words:
            yield word.lower(), 1

    def reducer_count_words(self, word, values):
        yield word, sum(values)

    def mapper_make_counts_key(self, word, count):
        yield str(count).rjust(4,'0'), word

    def reducer_output_words(self, count, words):
        for word in words:
            yield count, word

if __name__ == '__main__':
    MapReduceWordFreqCounter.run()           

2 个答案:

答案 0 :(得分:1)

您必须为您的工作设置自定义排序比较器。

如果你用java编写它,它看起来像

job.setSortComparatorClass(SortKeyComparator.class);

你必须提供一个提供逆序的课程

public class SortKeyComparator extends Text.Comparator {

    @Override
    public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
        return (-1) * super.compare(b1, s1, l1, b2, s2, l2);
    }
}

我猜python hadoop api有一些类似的方法来做这个技巧。

答案 1 :(得分:0)

对于MRJob Reduce步骤,不期望结果应按键'count'排序。

此处,MRJob导入允许您在本地和AWS Elastic MapReduce群集上运行代码。 MRJob执行繁重的工作,因为它使用Yarn API和Hadoop流在地图和减少作业之间进行分布式数据传输。

例如,要在本地运行,您可以将此MRJob运行为: python MapReduceWordFreqCounter.py books.txt> counts.txt

要在单个EMR节点上运行: python MapReduceWordFreqCounter.py -r emr books.txt> counts.txt

在25个EMR节点上运行: python MapReduceWordFreqCounter.py -r emr --num-ec2-instances = 25 books.txt> counts.txt

对分布式EMR作业进行故障排除(替换您的作业ID): python -m mrjob.tools.emr.fetch_logs --find-failure j-1NXEMBAEQFDFT

这里,当在四个节点上运行时,减少的结果是有序的,但在输出文件中有四个不同的部分。事实证明,强制减速器生成单个有序文件与在运行后作业步骤中排序结果相比,没有性能优势。因此,解决此特定问题的一种方法是使用Linux命令sort:

sort word_frequency_list.txt > sorted_word_frequency_list.txt

产生这些“尾”结果:

“0970”“的” “1191”“一个” “1292”“the” “1420”“你的” “1561”“你” “1828”“到”

更一般地说,Hadoop之上的框架是这种处理的理想选择。对于此问题,可以使用Pig读取已处理的文件并对计数进行排序。

Pig可以通过Grunt shell或Pig脚本运行(使用区分大小写的Pig Latin语法)。 Pig脚本遵循以下模板: 1)读取数据的LOAD语句 2)处理数据的一系列“转换”语句 3)用于保存结果的DUMP / STORE语句

使用猪订购计数:

reducer_count_output = LOAD 'word_frequency_list.txt' using PigStorage('  ') AS (word_count:chararray, word_name:chararray);
counts_words_ordered = ORDER reducer_count_output BY word_count ASC;
STORE counts_words_ordered INTO 'counts_words_ordered' USING PigStorage(':', '-schema');