我有一组带时间戳的事件数据,我想知道这些事件发生的平均值(算术平均值)和标准偏差(以小时为单位)。时间戳以UTC时区为单位,但事件是可能在不同时区发生的用户活动的结果,例如, UTC + 12,我不知道哪个。
这似乎很容易做到,但由于24小时的周期性,它并不明显。 (例如23和0小时在实践中靠得很近,但不是数学上的。)
以下是一个例子:
考虑到这些时间:3, 4, 3, 0, 21, 23, 4
,平均值看起来是8.3,标准偏差(人口)是8.8。但是,如果这些事件发生在UTC + 12中,那将是不正确的,因为"真实"小时为15, 16, 15, 12, 9, 11, 16
,平均值为13.4,标准开发(pop)2.6。
计算正确均值的最佳方法是什么(UTC为13.4)和stddev(pop)(2.6)?
示例数据(events
表):
id | timestamp
---+--------------------
1 | 2016-05-20 03:00:00
2 | 2016-05-20 04:00:00
3 | 2016-05-20 03:00:00
4 | 2016-05-20 00:00:00
5 | 2016-05-20 21:00:00
6 | 2016-05-20 23:00:00
7 | 2016-05-20 04:00:00
我现在正在使用的PostgreSQL查询如下:
SELECT CAST(avg(extract(epoch FROM timestamp::TIME)) AS dec(18, 10)),
CAST(stddev_pop(extract(epoch FROM timestamp::TIME)) AS dec(18, 10))
FROM events
目前的结果:
Mean | Stddev
-----------------+-----------------
29828.5714285714 | 31602.4282198023
(这是在几秒钟内,这个小时是平均8.3和std dev 8.8。)
预期结果是~13.4,标准差~2.6。
答案 0 :(得分:1)
您可以使用AT TIME ZONE转换时区。
SET TIME ZONE 'UTC';
WITH
test(id, dummy_time) as
(
values
(1, TIMESTAMP '2016-05-20 03:00:00'),
(2, TIMESTAMP '2016-05-20 04:00:00'),
(3, TIMESTAMP '2016-05-20 03:00:00'),
(4, TIMESTAMP '2016-05-20 00:00:00'),
(5, TIMESTAMP '2016-05-20 21:00:00'),
(6, TIMESTAMP '2016-05-20 23:00:00'),
(7, TIMESTAMP '2016-05-20 04:00:00')
)
SELECT avg(date_part('HOUR', dummy_time AT TIME ZONE 'UTC+12')) as AVERAGE_HOUR,
stddev_pop(date_part('HOUR', dummy_time AT TIME ZONE 'UTC+12')) as STDEV_HOUR
FROM test
这给出了你想要的13.4均值和2.6 stdev。