有人可以举例说明地图中的中位数/分位数的计算吗?
我对Datafu的中位数的理解是'n'映射器对它进行排序 数据并将数据发送到负责排序的“1”减速器 来自n个映射器的所有数据并找到中位数(中间值) 我的理解是否正确?,
如果是这样,这种方法是否适用 大量的数据,因为我可以清楚地看到一个单一的减速机 努力完成最后的任务。 谢谢
答案 0 :(得分:13)
试图找到一个系列中的中位数(中间数)将要求1个reducer传递整个数字范围,以确定哪个是'中间'值。
根据输入集中值的范围和唯一性,您可以引入组合器来输出每个值的频率 - 减少发送到单个reducer的地图输出的数量。然后,您的减速器可以使用排序值/频率对来识别中位数。
另一种可以缩放的方法(再次,如果您知道值的范围和粗略分布)是使用自定义分区器按范围桶分配键(0-99转到减速器0,1-100-199到减速器2) , 等等)。然而,这将需要一些辅助工作来检查减速器输出并执行最终中位数计算(例如,知道每个减速器中的键数,您可以计算哪个减速器输出将包含中位数,以及在哪个偏移处)
答案 1 :(得分:7)
你真的需要完全中位数和分位数吗?
很多时候,你最好只获得近似值,并使用它们,特别是如果你使用它,例如数据分区。
事实上,你可以使用近似分位数来加速找到精确的分位数(实际上在O(n/p)
时间内),这里是策略的大致轮廓:
O(n)
中)以查找真正的分位数。每个步骤都是线性时间。最昂贵的步骤是第3部分,因为它需要重新分配整个数据集,因此它会生成O(n)
网络流量。
您可以通过为第一次迭代选择“备用”分位数来优化过程。说,你想找到全球中位数。您无法轻松地在线性过程中找到它,但是当它被分成k个分区时,您可能将其缩小到数据集的1 / kth。因此,不是让每个节点报告其中值,而是让每个节点另外报告(k-1)/(2k)和(k + 1)/(2k)处的对象。这应该允许您缩小真实中位数必须显着位置的值的范围。因此,在下一步中,您可以将每个节点将所需范围内的对象发送到单个主节点,并仅选择此范围内的中位数。
答案 2 :(得分:2)
O((n log n)/ p)对其进行排序,然后按O(1)得到中位数。
是的......你可以获得O(n / p),但是你不能在Hadoop中使用开箱即用的排序功能。我只是排序并得到中心项目,除非你可以证明2-20小时的开发时间来编码并行的第k个最大算法。
答案 3 :(得分:0)
在许多实际场景中,数据集中值的基数相对较小。在这种情况下,使用两个MapReduce作业可以有效地解决问题:
作业1.将大幅减少数据量,并且可以完全并行执行。作业2的缩减器只需处理n
(n
= cardinality of your value set
)个项而不是所有值,就像天真的方法一样。
下面是作业2的示例缩减器。它是可以在Hadoop流中直接使用的python脚本。假设数据集中的值为ints
,但double
s
import sys
item_to_index_range = []
total_count = 0
# Store in memory a mapping of a value to the range of indexes it has in a sorted list of all values
for line in sys.stdin:
item, count = line.strip().split("\t", 1)
new_total_count = total_count + int(count)
item_to_index_range.append((item, (total_count + 1, new_total_count + 1)))
total_count = new_total_count
# Calculate index(es) of middle items
middle_items_indexes = [(total_count / 2) + 1]
if total_count % 2 == 0:
middle_items_indexes += [total_count / 2]
# Retrieve middle item(s)
middle_items = []
for i in middle_items_indexes:
for item, index_range in item_to_index_range:
if i in range(*index_range):
middle_items.append(item)
continue
print sum(middle_items) / float(len(middle_items))
此答案建立在最初来自answer Chris White的建议之上。答案建议使用组合器作为计算值的频率的平均值。但是,在MapReduce中,不能保证始终执行组合器。这有一些副作用: