2014-11-24 56 views
0

我有一个在MongoDB中的文档集合,我想计算一些属性的CDF并将其返回或存储在数据库中。很显然,为每个文档添加一个新属性并不是一个好方法,我可以稍后使用一个近似值。这更多的是一个理论问题。使用MapReduce在MongoDB中的累积分布

所以我决定用计算CDF的离散间隔采样与MapReduce工作,像这样(只是算法):

  1. 获取countminmax属性someAttr
  2. 假设min = 5max=70count = 200
  3. map()for (i=this.someAttr; i < max+1; i++) { emit(i, 1) }
  4. reduce()只是返回每个键的总和。
  5. finalize()中,将减少的输出除以记录计数:return val/count

这确实输出,但是从CDF样本,收集..

正如你在这里看到的间隔步骤是1,但这种方法的巨大效率低下是有可能的滔天量即使只有一小部分文档,甚至可以从单个文档中发布,因此这显然不具有可扩展性,并且不起作用。

输出看起来是这样的:

{ _id: 5, val: 0} 
{ _id: 6, val: 0.04} 
{ _id: 7, val: 0.04} 
... 
{ _id: 71, val: 1.0} 

在这里,我可以轻松地获得CDF的近似值为任意值,甚至它们之间的插值,如果这是合理的。

有人能告诉我你将如何用MapReduce(或可能没有MapReduce)计算CDF(样本)?

回答

1

根据定义,一个属性a累积分布函数F_a

F_a(x) = # documents with attribute value <= x/# of documents 

定义所以,你可以计算CDF与

F_a(x) = db.collection.count({ "a" : { "lte" : x })/db.collection.count({ "a" : { "$exists" : true } }) 

计数分母假设你不想要统计丢失a字段的文档。 a上的索引将使这个速度更快。

您可以使用它来计算cdf的样本或只是按需计算cdf。不需要map-reduce。

+0

谢谢,显然没有跨越我的想法:)我忘了提及我需要整个示例数组,以便在mapreduce内部进一步使用,所以我基本上不需要'on demand'CDF for文档。如果我用这个构建阵列,你的解决方案当然会更好,这就是我现在要做的。 我还在想,如果数据集太大或者样本需要更精细的时间间隔,是否可以使用mapreduce来完成。我的意思是说mapreduce方法比很多方法要好(假设MR中有一个合理的算法)。 – tamacun 2014-11-25 08:12:03