繁体   English   中英

使用 Hadoop map-reduce 并行计算值列表的中值

[英]calculate median of a list of values parallely using Hadoop map-reduce

我是 Hadoop mrjob 的新手。 我有一个文本文件,每行包含数据“id groupId 值”。 我正在尝试使用 Hadoop map-reduce 计算文本文件中所有值的中值。 但是当只计算中值时我被卡住了。 我得到的是每个 id 的中值,例如:

"123213"        5.0
"123218"        2
"231532"        1
"234634"        7
"234654"        2
"345345"        9
"345445"        4.5
"345645"        2
"346324"        2
"436324"        6
"436456"        2
"674576"        10
"781623"        1.5

output 应该类似于“所有值的中值是:####”。 我受到这篇文章https://computehustle.com/2019/09/02/getting-started-with-mapreduce-in-python/我的 python 文件median-mrjob.py的影响:

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

class MRMedian(MRJob):
    def steps(self):
        return [
            MRStep(mapper=self.mapper_get_stats, combiner=self.reducer_count_stats),
            MRStep(reducer=self.reducer_sort_by_values),
            MRStep(reducer=self.reducer_retrieve_median)
        ]

    def mapper_get_stats(self, _, line):
        line_arr = line.split(" ")
        values = int(float(line_arr[-1]))
        id = line_arr[0]
        yield id, values

    def reducer_count_stats(self, key, values):
        yield str(sum(values)).zfill(2), key

    def reducer_sort_by_values(self, values, ids):
        for id in ids:
            yield id, values

    def reducer_retrieve_median(self, id, values):
        valList=[]
        median = 0
        for val in values:
            valList.append(int(val))
        N = len(valList)
        #find the median
        if N % 2 == 0:
            #if N is even
            m1 = N / 2
            m2 = (N / 2) + 1
            #Convert to integer, match post
            m1 = int(m1) - 1
            m2 = int(m2) - 1
            median = (valList[m1] + valList[m2]) / 2 
        else:
            m = (N + 1) / 2
            # Convert to integer, match position
            m = int(m) - 1
            median = valList[m]
        yield (id, median)

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

我的原始文本文件大约有 100 万和 10 亿行数据,但我创建了一个包含任意数据的测试文件。 它的名称为input.txt

781623 2 2.3243
781623 1 1.1243
234654 1 2.122
123218 8 2.1245
436456 22 2.26346
436324 3 6.6667
346324 8 2.123
674576 1 10.1232
345345 1 9.56135
345645 7 2.1231
345445 10 6.1232
231532 1 1.1232
234634 6 7.124
345445 6 3.654376
123213 18 8.123
123213 2 2.1232

我关心的是价值观。 考虑到这可能是重复的。 我在终端运行命令行运行代码python median-mrjob.py input.txt

更新:作业的重点是不使用任何库,所以我需要手动对列表进行排序(或者可能是我理解的其中一些)并手动计算中位数(硬编码)。 否则使用 MapReduce 的目标就会消失。 在此分配中不允许使用 PySpark。 查看此链接以获取更多灵感计算中位数 map reduce

output 应该类似于“所有值的中值是:####”

然后你需要先将所有数据强制到一个 reducer(有效地破坏了使用 MapReduce 的目的)。

您可以通过不使用 ID 作为密钥并丢弃它来做到这一点

def mapper_get_stats(self, _, line):
    line_arr = line.split()
    if line_arr:  # prevent empty lines
        value = float(line_arr[-1])
        yield None, value

之后,排序并找到中位数(我固定了你的参数顺序)

def reducer_retrieve_median(self, key, values):
    import statistics
    yield None, f"median value of all values is: {statistics.median(values)}"  # automatically sorts the data

所以,只需两步

class MRMedian(MRJob):
    def steps(self):
        return [
            MRStep(mapper=self.mapper_get_stats),
            MRStep(reducer=self.reducer_retrieve_median)
        ]

对于给定的文件,您应该看到

null    "median value of all values is: 2.2938799999999997"

原始文本文件大约有 100 万和 10 亿行数据

这并不重要,但它是什么?

您应该先将文件上传到 HDFS,然后您可以使用比 MrJob 更好的工具,例如 Hive 或 Pig。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM