如何计算百分位数?
Posted
技术标签:
【中文标题】如何计算百分位数?【英文标题】:How to calculate the percentile? 【发布时间】:2013-08-31 07:55:20 【问题描述】:我有如下访问日志存储在 mongodb 实例中:
Time Service Latency
[27/08/2013:11:19:22 +0000] "POST Service A HTTP/1.1" 403
[27/08/2013:11:19:24 +0000] "POST Service B HTTP/1.1" 1022
[27/08/2013:11:22:10 +0000] "POST Service A HTTP/1.1" 455
Oracle 中是否有类似PERCENTILE_DISC
的分析函数来计算百分位数?
我想计算一段时间内的延迟百分位数。
【问题讨论】:
【参考方案1】:似乎仍然没有计算百分位数的本地方法,但通过组合几个聚合运算符,您可以获得相同的结果。
db.items.aggregate([
'$group':
'_id':
'league': '$league',
'base': '$base',
'type': '$type'
,
'value': '$push': '$chaosequiv'
,
'$unwind': '$value',
'$sort': 'value': 1,
'$group': '_id': '$_id', 'value': '$push': '$value',
'$project':
'_id': 1,
'value': '$arrayElemAt': ['$value', '$floor': '$multiply': [0.25, '$size': '$value']]
], allowDiskUse=True)
请注意,我在 pymongo 中编写了我的原始代码,以解决需要对第一组中的 3 个字段进行分组的问题,因此这可能比单个字段所需的更复杂。我会针对这个问题写一个解决方案,但我认为没有足够的具体信息。
【讨论】:
我知道流放之路交易工具的代码,当我看到它时。 :) 先排序再分组不行吗?而不是分组、展开、排序、再次分组。【参考方案2】:从Mongo 4.4
开始,$group
阶段有一个新的聚合运算符 $accumulator
,允许通过 javascript 用户定义的函数在文档分组时自定义累积文档。
因此,为了找到第 20 个百分位数:
// "a" : 25, "b" : 12
// "a" : 89, "b" : 73
// "a" : 25, "b" : 7
// "a" : 25, "b" : 17
// "a" : 89, "b" : 14
// "a" : 89, "b" : 17
// "a" : 25, "b" : 24
// "a" : 25, "b" : 15
// "a" : 25, "b" : 22
// "a" : 25, "b" : 94
db.collection.aggregate([
$group:
_id: "$a",
percentile:
$accumulator:
accumulateArgs: ["$b"],
init: function() return []; ,
accumulate: function(bs, b) return bs.concat(b); ,
merge: function(bs1, bs2) return bs1.concat(bs2); ,
finalize: function(bs)
bs.sort(function(a, b) return a - b );
return bs[Math.floor(bs.length*.2) + 1];
,
lang: "js"
])
// "_id" : 89, "percentile" : 17
// "_id" : 25, "percentile" : 15
累加器:
在场上积累b
(accumulateArgs
)
初始化为空数组 (init
)
在数组中累积b
项(accumulate
和merge
)
最后对b
项目(finalize
)执行百分位数计算
【讨论】:
【参考方案3】:计算从 0 到 100 的百分位数(第 5 步)
// "session": 1, "date" : 2013-08-27 11:00::00, "latency" : 403
// "session": 1, "date" : 2013-08-27 11:00::01, "latency" : 1022
// "session": 1, "date" : 2013-08-27 11:00::02, "latency" : 455
// "session": 1, "date" : 2013-08-27 11:00::02, "latency" : 307
// "session": 2, "date" : 2013-08-27 12:00::00, "latency" : 403
// "session": 2, "date" : 2013-08-27 12:00::01, "latency" : 1022
// "session": 2, "date" : 2013-08-27 12:00::02, "latency" : 455
// "session": 2, "date" : 2013-08-27 12:00::02, "latency" : 307
var interval = 5
db.getCollection.aggregate([
$group:
_id: $toString: "$session" ,
value: $push: "$atency"
,
$addFields:
index : $range: [0, 100, interval]
,
$unwind: "$index",
$addFields:
p_index : $divide: ["$index", 100]
,
$addFields:
percentile_x : $toDouble: '$arrayElemAt': ['$value', '$floor': '$multiply': ["$p_index", '$size': '$value']]
,
$project:
'percentile': "$index",
'value': "$percentile_x"
,
$sort:
percentile: 1
])
【讨论】:
以上是关于如何计算百分位数?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 JavaScript(或 PHP)中获取数组的中位数和四分位数/百分位数?
Pandas .. 分位数函数是不是需要排序数据来计算百分位数?
在 SQL 中分析并形成分位数并计算落在各个分位数中的值的百分比