我正在尝试使用python中的SQLAlchemy计算中值作为时间的函数。我要找的是在给定日期以下的所有时间的中位数。
所以一些示例数据是
Date Value
2017-08-02 0.11
2017-08-22 0.34
2017-08-24 0.66
2017-09-05 1.23
2017-09-26 0.15
2017-10-07 0.99
2017-10-13 1.01
2017-10-22 0.44
2017-10-28 0.89
我想要计算的是8月份所有值的中位数,然后是8月份和 9月份所有值的中位数,然后是8月份所有值的中位数和九月和十月。
示例输出将是这样的。
Date Median
2017-08-01 0.34
2017-09-01 0.34
2017-10-01 0.66
在实际数据中有更多的值,因此中位数实际上是有意义的。我事先并不知道每月会有多少参赛作品。
非常感谢任何帮助!
答案 0 :(得分:0)
我相当确定存在更好的方法,但您可以从数据中选择月份 - 由此处组中的最大日期表示 - 然后分别计算每个月及以下的第50个百分点:
months = select([func.max(tbl.c.date).label('date')]).\
group_by(func.date_trunc('month', tbl.c.date)).\
alias('months')
percentiles = select([
func.percentile_cont(0.5).
within_group(tbl.c.value).
label('median')]).\
where(tbl.c.date <= months.c.date).\
lateral('percentiles')
query = select([months.c.date,\
percentiles.c.median]).\
order_by(months.c.date)
结果是:
In [8]: engine.execute(query).fetchall()
2017-10-25 16:44:18,637 INFO sqlalchemy.engine.base.Engine SELECT months.date, percentiles.median
FROM (SELECT max(foo.date) AS date
FROM foo GROUP BY date_trunc(%(date_trunc_1)s, foo.date)) AS months, LATERAL (SELECT percentile_cont(%(percentile_cont_1)s) WITHIN GROUP (ORDER BY foo.value) AS median
FROM foo
WHERE foo.date <= months.date) AS percentiles ORDER BY months.date
2017-10-25 16:44:18,637 INFO sqlalchemy.engine.base.Engine {'percentile_cont_1': 0.5, 'date_trunc_1': 'month'}
Out[8]:
[(datetime.date(2017, 8, 24), 0.34),
(datetime.date(2017, 9, 26), 0.34),
(datetime.date(2017, 10, 28), 0.66)]
如果需要,截止日期到月的第一天应该是非常简单的。请注意,您也可以使用标量子查询代替LATERAL。