日期时间范围之间的 Python Pandas 累积列

Posted

技术标签:

【中文标题】日期时间范围之间的 Python Pandas 累积列【英文标题】:Python Pandas cumulative column between datetime ranges 【发布时间】:2015-12-19 01:43:16 【问题描述】:

我正在尝试使用 pandas 数据透视表在任意两个给定日期时间范围之间生成一个累积列,但目前尚不清楚如何实际实现这一点。我可以为所有日期创建一个,如下所示。

所有日期时间:

                 sum count  cum_sum
dt
2015-01-01 10:00:00 10   10
2015-01-01 12:00:00 20   30
2015-01-01 13:00:00 30   60
2015-01-02 10:00:00 10   70
2015-01-02 12:00:00 20   90
2015-01-02 13:00:00 30  120

在两个指定的日期时间之间:

                     sum count  cum_sum
dt
2015-01-01 12:00:00 20   30
2015-01-01 13:00:00 30   60
2015-01-02 10:00:00 10   70
2015-01-02 12:00:00 20   90

有没有办法生成上面的表格,但是从查询中的开始日期开始累积(或者在数据框本身中这样做?)。

我的代码:

import pandas as pd
import numpy as np
from datetime import datetime

data=[
'count': 10, 'dt': datetime.strptime("20150101 10:00", "%Y%m%d %H:%M") ,
'count': 20, 'dt': datetime.strptime("20150101 12:00", "%Y%m%d %H:%M") ,
'count': 30, 'dt': datetime.strptime("20150101 13:00", "%Y%m%d %H:%M") ,
'count': 10, 'dt': datetime.strptime("20150102 10:00", "%Y%m%d %H:%M") ,
'count': 20, 'dt': datetime.strptime("20150102 12:00", "%Y%m%d %H:%M") ,
'count': 30, 'dt': datetime.strptime("20150102 13:00", "%Y%m%d %H:%M") 
]

df = pd.DataFrame(data)
df['cum_sum']=df['count'].cumsum()
pivot=pd.pivot_table(df, index=['dt'],aggfunc=[np.sum])
print (pivot)
result = pivot.query('dt >= "0" and dt <="   1"'.format(
    datetime.strptime("20150101 11:00", "%Y%m%d %H:%M"),
    datetime.strptime("20150102 12:00", "%Y%m%d %H:%M")
))
print (result)

编辑:我想在 2 个日期范围之间创建一个累积列,但有子标准。

data=[
    'loc': 'Japan', 'count': 10, 'dt': datetime.strptime("20150101 10:00",         "%Y%m%d %H:%M") ,
    'loc': 'Japan', 'count': 20, 'dt': datetime.strptime("20150101 12:00", "%Y%m%d %H:%M") ,
    'loc': 'Japan', 'count': 30, 'dt': datetime.strptime("20150101 13:00", "%Y%m%d %H:%M") ,
    'loc': 'London', 'count': 10, 'dt': datetime.strptime("20150102 10:00", "%Y%m%d %H:%M") ,
'loc': 'London', 'count': 20, 'dt': datetime.strptime("20150102 12:00", "%Y%m%d %H:%M") ,
'loc': 'NewYork', 'count': 30, 'dt': datetime.strptime("20150102 13:00", "%Y%m%d %H:%M") 
    ]

所以输出将针对特定的日期时间范围:

Loc                      Count cum_sum 
Japan
    2015-01-01 10:00:00 10       10
    2015-01-01 13:00:00 30       40
    2015-01-02 13:00:00 30       70
London
    2015-01-01 12:00:00 20       20
    2015-01-02 10:00:00 10       20
    2015-01-02 12:00:00 20       40

【问题讨论】:

【参考方案1】:

您可以使用日期时间列重新定义 Dataframe 的索引并使用 .ix,例如 this:

df.index = df.dt
time1=datetime.strptime("20150101 11:00", "%Y%m%d %H:%M")
time2=datetime.strptime("20150102 12:00", "%Y%m%d %H:%M")
df.ix[time1:time2]['count'].cumsum()

如果您想包含第一天的所有值,您可以使用time1 datetime 对象的date() 函数:

df.ix[time1.date():time2]['count'].cumsum()

给予:

2015-01-01 10:00:00    10
2015-01-01 12:00:00    30
2015-01-01 13:00:00    60
2015-01-02 10:00:00    70
2015-01-02 12:00:00    90
Name: count, dtype: int64

要得到你要求的输出,从time1开始,你可以添加[time1:]

df.ix[time1.date():time2]['count'].cumsum()[time1:]

给予:

2015-01-01 12:00:00    30
2015-01-01 13:00:00    60
2015-01-02 10:00:00    70
2015-01-02 12:00:00    90
Name: count, dtype: int64

编辑

在回答您的后续问题时,您可以使用 groupby(取自 this answer):

df.index=df.dt
df=df.ix[time1.date():time2]['count'].reset_index() # filter times and remove date index
df.groupby(by=['loc','dt']).sum().groupby(level=[0]).cumsum()

给予:

                            count
loc     dt                        
Japan   2015-01-01 10:00:00     10
        2015-01-01 12:00:00     30
        2015-01-01 13:00:00     60
London  2015-01-02 10:00:00     10
        2015-01-02 12:00:00     30
NewYork 2015-01-02 13:00:00     30

【讨论】:

谢谢,这就是我要找的!我将其应用于 dt 索引不再是唯一的 DF,即。以及 'count': 0 将有 'Location': 'Japan',如果我想按位置计算 2 个日期范围(如上所述)之间的累积值,(位置 -> 日期 -> Accumulated Count) 你知道如何实现吗? 在上面进行了编辑以证明这一点。 希望我有代表对此表示赞同。 'loc' 出现关键错误,似乎 ix 过滤器删除了此列(所以我在分组之前将其添加回) temp=df['loc'] 然后 df['loc']=temp 在过滤器之后。 【参考方案2】:

以下是一种简单但不是很复杂的处理方式:

df = pd.DataFrame(data)
df.set_index('dt', inplace=True)
df['cumsum'] = df['count']
df.loc[df.index < datetime.strptime("20150101 11:00", "%Y%m%d %H:%M"), 'cumsum'] = 0.0
df['cumsum'] = df['cumsum'].cumsum()
print(df)

给出以下结果:

                     count  cumsum
dt                                
2015-01-01 10:00:00     10       0
2015-01-01 12:00:00     20      20
2015-01-01 13:00:00     30      50
2015-01-02 10:00:00     10      60
2015-01-02 12:00:00     20      80
2015-01-02 13:00:00     30     110

【讨论】:

谢谢 - 虽然这如何适用于一个范围,有没有办法删除不属于这个范围的日期,因为 0 可能是有效值我不想过滤掉仅此而已。 如果您对将值保持在范围之外不感兴趣,那么它就更简单了。试试df = df[df.index &gt;= datetime.strptime("20150101 11:00", "%Y%m%d %H:%M")]df = df[df.index &lt;= datetime.strptime("20150102 12:00", "%Y%m%d %H:%M")] 之类的东西,然后像你一样计算cumsum。除非我错过了什么?

以上是关于日期时间范围之间的 Python Pandas 累积列的主要内容,如果未能解决你的问题,请参考以下文章

Python pandas根据日期范围按升序过滤数据

Python 帮助 - 添加基于日期范围创建列

Python数据分析pandas日期范围date_range

Python Pandas 插值:在缺失的日期范围内重新分配值

Python pandas 转换(yy/mm)日期格式并选择特定时间范围

有没有办法用两个日期之间的每小时日期时间有效地填充 python 中的 pandas df 列?