大熊猫按时间分组并指定开始时间

时间:2017-08-25 17:45:53

标签: python pandas

- 编辑我注意到我输入的时间不是我想要的。我将12点之后的时间转换为24小时时间约定。但是,unutbu的答案应该仍然清楚。

- 第二次编辑。我改变了数据以做出更好的例子。

以下是按日期编制索引的时间序列。我想从start_datetime开始进行聚合,并根据下面的timedelta继续聚合(9.5小时= 34200秒)。

def main():

    # start_datetime = datetime.datetime(2013, 1, 1, 8)
    # end_datetime = datetime.datetime(2013, 1, 1, 5, 30)
    s = pd.Series(
        np.arange(2, 10),
        pd.to_datetime([
            '20130101 7:34:04', '20130101 8:34:08', '20130101 10:34:08',
            '20130101 12:34:15', '20130101 13:34:28', '20130101 12:34:54',
            '20130101 14:34:55', '20130101 17:29:12']))

    print(s)
    bar_size = datetime.timedelta(seconds=60*60*9.5)
    time_group = pd.Grouper(
        freq=pd.Timedelta(bar_size), closed='left', label='right')
    foobar = s.groupby(time_group).agg(np.sum)
    print(foobar)

if __name__ == "__main__":
    main()

运行上面的代码将输出以下内容:

2013-01-01 09:30:00     5
2013-01-01 19:00:00    39
Freq: 570T, dtype: int64

大熊猫内部决定从午夜而不是上午8:00开始分组。我无法找到一种方法来强制数据帧在上午8:00开始分组。有没有人有使用pandas功能的解决方案?

4 个答案:

答案 0 :(得分:3)

使用sys.path.append('\Users\Name\Documents\Python\MainFolder')将起点移动480分钟(8小时)。 单位是几分钟,因为石斑鱼的频率是base=480(T,这里,表示分钟):

570T

产量

import datetime
import pandas as pd

def main():

    start_datetime = datetime.datetime(2013, 1, 1, 8)
    s = pd.Series(
        range(8),
        pd.to_datetime([
            '20130101 8:34:04', '20130101 10:34:08', '20130101 10:34:08',
            '20130101 12:34:15', '20130101 1:34:28', '20130101 3:34:54',
            '20130101 4:34:55', '20130101 5:29:12']))

    bar_size = datetime.timedelta(seconds=60*60*9.5)
    time_group = pd.Grouper(freq=bar_size, closed='left', label='right', 
                            base=480)
    foobar = s.groupby(time_group).agg(sum)
    print(foobar)

if __name__ == "__main__":
    main()

在内部,2013-01-01 08:00:00 22 2013-01-01 17:30:00 6 Freq: 570T, dtype: int64 给出频率a TimeGrouper is returned

pd.Grouper

因此传递给In [81]: time_group Out[81]: <pandas.core.resample.TimeGrouper at 0x7f1499a32198> 的参数实际上传递给pd.Grouper

pd.TimeGrouper

In [82]: pd.TimeGrouper? Init signature: pd.TimeGrouper(self, freq='Min', closed=None, label=None, how='mean', nperiods=None, axis=0, fill_method=None, limit=None, loffset=None, kind=None, convention=None, base=0, **kwargs) 文档不解释TimeGrouper参数,但其含义与base中的含义相同:

df.resample

答案 1 :(得分:1)

以下内容可让您将开始时间向前滑动八小时:

(s.index + pd.Timedelta('9 hours 30 minutes')).strftime('%Y-%m-%d')
# array([u'2013-01-01', u'2013-01-01', u'2013-01-01', u'2013-01-01', 
# u'2013-01-01', u'2013-01-01', u'2013-01-01', u'2013-01-01'], 
# dtype='<U10')

然后你可以打电话:

s.groupby((s.index + pd.Timedelta('9 hours 30 minutes')).strftime('%Y-%m-%d')).agg(sum)
# 2013-01-01    28

您还可以完全依赖pandas datetime模块来实现您的功能,而不是单独导入datetime

import pandas as pd


def main():

    start_datetime = pd.datetime(2013, 1, 1, 8)

    s = pd.Series(
        range(8),
        pd.to_datetime([
            '20130101 8:34:04', '20130101 10:34:08', '20130101 10:34:08',
            '20130101 12:34:15', '20130101 1:34:28', '20130101 3:34:54',
            '20130101 4:34:55', '20130101 5:29:12']))

    time_group = (s.index + pd.Timedelta('9 hours 30 minutes')).strftime('%Y-%m-%d')
    foobar = s.groupby(time_group).agg(sum)
    print(foobar)

答案 2 :(得分:0)

非常有趣的是,pandas.Grouper的文档说:

  

pandas.Grouper(key = None,level = None,freq = None,axis = 0,sort = False)

     

...

     

base:int,默认为0

Only when freq parameter is passed.

关于 base 参数没有任何解释。而且它甚至不在构造函数参数列表中。它只说需要int。 但是,您实际上可以传入float,以便它可以将分组间隔移动一小部分时间。例如,如果您的freq ='1D'并且您将base = 0.5设置为0,则组边界将是每天12pm,而不是0am。

答案 3 :(得分:0)

pandas 1.1.0 引入了origin参数,它是实现此目的的直接方法(还请注意9h30min的{​​{1}}表示法,更多表示法{ {3}}):

freq

对于熊猫<1.1.0 ,您可以执行以下操作以获得更通用的解决方案:

df = pd.DataFrame(pd.to_datetime([
            '2013-01-01 8:34:04', '2013-01-01 10:34:08', '2013-01-01 10:34:08',
            '2013-01-01 12:34:15', '2013-01-01 1:34:28', '2013-01-01 3:34:54',
            '2013-01-01 4:34:55', '2013-01-01 5:29:12']), columns =['the_date'])
# dummy column with ones
df['other'] = 1

# sum the other column aggregated by the date
df.groupby(pd.Grouper(key='the_date',freq='9h30min', origin='start'))['other'].sum()

基本上,您可以使用最小日期来计算基数(df.groupby(pd.Grouper(key='the_date',freq='9h30min', base=df.the_date.min().hour * 60 + df.the_date.min().minute))['other'].sum() )。

here

(此版本也弃用了{df.the_date.min().hour * 60 + df.the_date.min().minute