在Python中对一系列日期进行分组

时间:2015-10-11 18:17:03

标签: python python-2.7 python-3.x pandas

我有以下数据库,我想将PAS_DATE分组为3天,例如表格2015-03-06至2015-03-09

PAS_DATE    RED_DATE       TOT
2015-03-06  2015-03-07     2
            2015-03-17    14
            2015-12-22     1
2015-03-07  2015-03-08     3
            2015-03-19     6
            2015-10-14     2
            2015-12-07     1
2015-03-08  2015-09-16     8
2015-03-09  2015-03-09     7
            2015-03-15     6
            2015-03-18     8
            2015-04-04    15
            2015-04-12    19
            2015-05-04    44
            2015-08-17     5
            2015-09-09    13
            2015-12-06     3
            2015-12-13     3
2015-03-10  2015-03-10     7

输出应为:

PAS_DATE    RED_DATE      TOT
2015-03-09  2015-03-07     2
            2015-03-17    14
            2015-12-22     1
            2015-03-08     3
            2015-03-19     6
            2015-10-14     2
            2015-12-07     1
            2015-09-16     8
            2015-03-09     7
            2015-03-15     6
            2015-03-18     8
            2015-04-04    15
            2015-04-12    19
            2015-05-04    44
            2015-08-17     5
            2015-09-09    13
            2015-12-06     3
            2015-12-13     3
2015-03-12  2015-03-10     7

有没有办法在没有Pandas或Python迭代的情况下执行此代码?

1 个答案:

答案 0 :(得分:0)

我不知道,如果这比使用带有iterrows()的循环更有效,但这是一种方法(好吧,虽然它很hacky):

df = pd.DataFrame(pd.date_range("2015-01-01","2015-01-10"), columns=['PAS_DATE'])

df['dt_since_first'] = (df.PAS_DATE - df.PAS_DATE.min()).dt.days
df['shift'] = pd.to_timedelta(2 - np.mod(df.dt_since_first, 3), unit='d')
df['for_group_by'] = df.PAS_DATE + df['shift']
  1. 创建一个包含该列的新列 timedelta自列中的第一个日期以来将其转换为 整数,作为天数。
  2. 现在使用mod3查找PAS_DATE必须移动多少天才能获得 到你的3天(ceil)binning并将它转换回timedelta对象。
  3. 只需按此时间点移动PAS_DATE。
  4. 这是输出:

        PAS_DATE  dt_since_first  shift for_group_by
    0 2015-01-01               0 2 days   2015-01-03
    1 2015-01-02               1 1 days   2015-01-03
    2 2015-01-03               2 0 days   2015-01-03
    3 2015-01-04               3 2 days   2015-01-06
    4 2015-01-05               4 1 days   2015-01-06
    5 2015-01-06               5 0 days   2015-01-06
    6 2015-01-07               6 2 days   2015-01-09
    7 2015-01-08               7 1 days   2015-01-09
    8 2015-01-09               8 0 days   2015-01-09
    9 2015-01-10               9 2 days   2015-01-12
    

    您可以在同一列上迭代执行此操作,我只是为每个步骤使用了不同的列以便于理解...

    编辑评论

    我猜,你的PAS_DATE列是dtype = object,尽管你的条目是dtype = np.datetime [64]。有一些强有力的理由,为什么要避免这种情况。

    我曾经有过这样的情况,我需要一个很长的DataFrame,直到我发现它我经历了地狱。有各种各样的例外,我在Stackoverflow上花了无数个小时试图解决我的问题。此外,一切都非常缓慢,最重要的是,内存需要将df保存得非常大。

    发生了什么事。您的列是dtype = object,这意味着它只保存指向大型datetime对象集合的指针。如果它是dtype = np.datetime [64],它将只保存64位的日期时间信息。

    尝试查看信息,它应该是这样的:

    print df.info()
    
    Output:
    <class 'pandas.core.frame.DataFrame'>
    Int64Index: 10 entries, 0 to 9
    Data columns (total 4 columns):
    PAS_DATE          10 non-null datetime64[ns]
    dt_since_first    10 non-null int64
    shift             10 non-null timedelta64[ns]
    for_group_by      10 non-null datetime64[ns]
    dtypes: datetime64[ns](2), int64(1), timedelta64[ns](1)
    memory usage: 400.0 bytes
    

    现在要转换您的PAS_DATE列,请尝试以下方法:

    df.PAS_DATE = df.PAS_DATE.convert_objects(convert_dates='coerce')
    

    顺便说一句,您应该在代码中尽快执行此操作。并且应该也可以在您的其他日期列中执行此操作。在转换之前和之后执行df.info()。告诉我们,内存使用情况有什么不同。