如何使用 MapReduce 对键值对进行排序? 按升序计数按降序计数

问题描述

我一直在使用 MapReduce,对它仍然很陌生,并且想知道我是否可以就我无法回答的问题获得一些帮助: 我有一个包含日期和计数的 txt 文件,并希望根据它们各自的计数按升序对日期进行排序。文本文件如下所示:

enter image description here

我环顾四周,发现了一些这样的代码

import re

从 mrjob.job 导入 MRJob 从 mrjob.step 导入 MRStep

WORD_RE = re.compile(r"[\w']+")

类 MRWordFrequencyCount(MRJob):

def steps(self):
    return [
        MRStep(
            mapper=self.mapper_extract_words,combiner=self.combine_word_counts,reducer=self.reducer_sum_word_counts
        ),MRStep(
            reducer=self.reduce_sort_counts
        )
    ]

def mapper_extract_words(self,_,line):
    for word in WORD_RE.findall(line):
        yield word.lower(),1

def combine_word_counts(self,word,counts):
    yield word,sum(counts)

def reducer_sum_word_counts(self,key,values):
    yield None,(sum(values),key)

def reduce_sort_counts(self,word_counts):
    for count,key in sorted(word_counts,reverse=True):
        yield ('%020d' % int(count),key)

但这似乎太复杂了,因为正如您从postedDates txt 文件中看到的那样,我已经有了密钥及其各自的计数。那么我是否只需要添加第二步,它只是一个使用“sorted(counts)”对键和值列表进行排序的 reducer 函数

对您的时间表示亲切的问候。

解决方法

您是对的,鉴于您的特定设置,当然可以使用单个 MapReduce 执行您的任务。

您可以跳过示例中的初始步骤,因为您已经有了每个日期(键)的计数。您只需执行第二步,将这些对组合成元组并根据 countdate

进行排序

按升序计数

import datetime

from mrjob.job import MRJob


class MRDateFrequencyCount(MRJob):

    def mapper(self,_,line):
        date,count = line.split(' ')
        yield None,(int(count),date)

    def reducer(self,dates):
        for count,date in sorted(dates,key=lambda x: (x[0],datetime.datetime.strptime(x[1],'"%Y-%m-%d"'))):
            yield date,count


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

产生输出:

"\"2006-11-01\""    1
"\"2006-12-21\""    1
"\"2006-12-11\""    2
"\"2007-03-12\""    3

按降序计数

import datetime

from mrjob.job import MRJob


class MRDateFrequencyCount(MRJob):

    def mapper(self,key=lambda x: (-x[0],count


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

产生输出:

"\"2007-03-12\""    3
"\"2006-12-11\""    2
"\"2006-11-01\""    1
"\"2006-12-21\""    1

注意:如果图像中数据的格式与我在下面测试的文本中显示的格式不同,则您需要更改 strptime 格式字符串 '"%Y-%m-%d"' .


两个 MRJob 都在没有配置的情况下运行,并在包含以下文本的文本文档上运行:

"2006-12-21" 1
"2007-03-12" 3
"2006-11-01" 1
"2006-12-11" 2

当然,如果您想更改哪个列(计数或日期)排在第一或第二,您可以在任一减速器中更改 yeild

您还可以使用字符串格式来去除数据集中日期周围的 "