使用特定日期对Pandas DataFrame进行重新采样

5

我有一个关于 Pandas 数据框重采样方法的问题。我的数据框每天只有一个观测值:

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randint(0,100,size=(366, 1)), columns=list('A'))
df.index = pd.date_range(datetime.date(2016,1,1),datetime.date(2016,12,31))

如果我想计算每个月的总和(或其他),我可以直接这样做:
EOM_sum = df.resample(rule="M").sum()

但是我有一个特定的日历(不规则频率):

import datetime
custom_dates = pd.DatetimeIndex([datetime.date(2016,1,13),
                             datetime.date(2016,2,8),
                             datetime.date(2016,3,16),
                             datetime.date(2016,4,10),
                             datetime.date(2016,5,13),
                             datetime.date(2016,6,17),
                             datetime.date(2016,7,12),
                             datetime.date(2016,8,11),
                             datetime.date(2016,9,10),
                             datetime.date(2016,10,9),
                             datetime.date(2016,11,14),
                             datetime.date(2016,12,19),
                             datetime.date(2016,12,31)])

如果我想计算每个时期的总和,我目前会在df中添加一个临时列,该列包含每行所属的时期结束时间,然后使用groupby执行操作:

df["period"] = custom_dates[custom_dates.searchsorted(df.index)]
custom_sum = df.groupby(by=['period']).sum()

然而这种方法相当不规范,看起来并不符合Python风格。在Pandas中有没有内置的方法可以做到这一点呢? 提前致谢。

不需要新列,您可以使用custom_sum = df.groupby(custom_dates[custom_dates.searchsorted(df.index)]).sum() - jezrael
Pandas的重新采样方法基于使用某种频率的索引。你使用的方法是正确的方法,请参考上面@jezrael的答案,以跳过添加的列。 - James
谢谢,我只是惊讶于 Pandas 中没有类似的功能,因为它与“重新采样”方法非常接近。 - JMat
1个回答

5

创建新列不是必要的,你可以通过将DatatimeIndex作为groupby的依据,因为lengthdflenght相同:

import pandas as pd
import numpy as np

np.random.seed(100)
df = pd.DataFrame(np.random.randint(0,100,size=(366, 1)), columns=list('A'))
df.index = pd.date_range(datetime.date(2016,1,1),datetime.date(2016,12,31))
print (df.head())
             A
2016-01-01   8
2016-01-02  24
2016-01-03  67
2016-01-04  87
2016-01-05  79

import datetime
custom_dates = pd.DatetimeIndex([datetime.date(2016,1,13),
                             datetime.date(2016,2,8),
                             datetime.date(2016,3,16),
                             datetime.date(2016,4,10),
                             datetime.date(2016,5,13),
                             datetime.date(2016,6,17),
                             datetime.date(2016,7,12),
                             datetime.date(2016,8,11),
                             datetime.date(2016,9,10),
                             datetime.date(2016,10,9),
                             datetime.date(2016,11,14),
                             datetime.date(2016,12,19),
                             datetime.date(2016,12,31)])

custom_sum = df.groupby(custom_dates[custom_dates.searchsorted(df.index)]).sum()
print (custom_sum)
               A
2016-01-13   784
2016-02-08  1020
2016-03-16  1893
2016-04-10  1242
2016-05-13  1491
2016-06-17  1851
2016-07-12  1319
2016-08-11  1348
2016-09-10  1616
2016-10-09  1523
2016-11-14  1793
2016-12-19  1547
2016-12-31   664

另一个解决方案是通过 custom_dates 添加新的 indexgroupby 使用从 searchsorted 函数输出的 numpy数组

print (custom_dates.searchsorted(df.index))
[ 0  0  0  0  0  0  0  0  0  0  0  0  0  1  1  1  1  1  1  1  1  1  1  1  1
  1  1  1  1  1  1  1  1  1  1  1  1  1  1  2  2  2  2  2  2  2  2  2  2  2
  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2
  2  3  3  3  3  3  3  3  3  3  3  3  3  3  3  3  3  3  3  3  3  3  3  3  3
  3  4  4  4  4  4  4  4  4  4  4  4  4  4  4  4  4  4  4  4  4  4  4  4  4
  4  4  4  4  4  4  4  4  4  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5
  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  6  6  6  6  6  6
  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  7  7  7  7  7  7
  7  7  7  7  7  7  7  7  7  7  7  7  7  7  7  7  7  7  7  7  7  7  7  7  8
  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8
  8  8  8  8  9  9  9  9  9  9  9  9  9  9  9  9  9  9  9  9  9  9  9  9  9
  9  9  9  9  9  9  9  9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 11 11 11 11 11 11
 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11
 11 11 11 11 12 12 12 12 12 12 12 12 12 12 12 12]

custom_sum = df.groupby(custom_dates.searchsorted(df.index)).sum()
custom_sum.index = custom_dates
print (custom_sum)
               A
2016-01-13   784
2016-02-08  1020
2016-03-16  1893
2016-04-10  1242
2016-05-13  1491
2016-06-17  1851
2016-07-12  1319
2016-08-11  1348
2016-09-10  1616
2016-10-09  1523
2016-11-14  1793
2016-12-19  1547
2016-12-31   664

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接