【问题标题】:Filtering Pandas DataFrame on last n dates在最后 n 个日期过滤 Pandas DataFrame
【发布时间】:2017-02-28 10:54:29
【问题描述】:

我有一个看起来像这样的 Pandas DF:

df

我想使用本地定义的 int 参数“days”过滤 DF。比如当days = 10时,我过滤的DF只有最后10个可用日期的数据。

到目前为止,我已经尝试了以下方法:

days=10    
cutoff_date = df["SeriesDate"][-1:] - datetime.timedelta(days=days)

但是,然后尝试使用以下方式输出过滤后的 DF:

df[df['SeriesDate'] > cutoff_date] 

我收到以下错误:

ValueError: Can only compare identically-labeled Series objects

我仍在学习 Python,因此我将不胜感激。

【问题讨论】:

  • 不确定我是否理解您的问题:您需要先为每一行创建一个截止日期,然后进行相应过滤?
  • 我想输出根据天数传递的值过滤的 DF。因此,如果 days = 10,则输出 DF 中的最后 10 个值。因此,如果最后一个可用日期是 2017 年 2 月 27 日,那么我的输出系列应该只有 2017 年 2 月 17 日之后的值
  • 您的数据框是否按日期索引?如果您发布数据示例会有所帮助。
  • 不,它没有按日期索引,我在这里发布了一个示例:i.stack.imgur.com/aknhX.jpg
  • 为什么要删除最后一项 df["SeriesDate"][-1:] by [-1:] ?然后系列不具有相同的索引(最后一项被删除),所以你得到错误。

标签: python python-2.7 pandas


【解决方案1】:

我认为您需要通过iloc 选择列SeriesDate 的最后一个值:

start = pd.to_datetime('2015-02-24')
rng = pd.date_range(start, periods=15, freq='20H')
df = pd.DataFrame({'SeriesDate': rng, 'Value_1': np.random.random(15)})  
print (df)
            SeriesDate   Value_1
0  2015-02-24 00:00:00  0.849160
1  2015-02-24 20:00:00  0.332487
2  2015-02-25 16:00:00  0.687638
3  2015-02-26 12:00:00  0.310326
4  2015-02-27 08:00:00  0.660795
5  2015-02-28 04:00:00  0.354475
6  2015-03-01 00:00:00  0.061312
7  2015-03-01 20:00:00  0.443908
8  2015-03-02 16:00:00  0.708326
9  2015-03-03 12:00:00  0.257419
10 2015-03-04 08:00:00  0.618363
11 2015-03-05 04:00:00  0.121625
12 2015-03-06 00:00:00  0.637324
13 2015-03-06 20:00:00  0.058292
14 2015-03-07 16:00:00  0.047624
days=10    
cutoff_date = df["SeriesDate"].iloc[-1] - pd.Timedelta(days=days)
print (cutoff_date)
2015-02-25 16:00:00

df1 = df[df['SeriesDate'] > cutoff_date] 
print (df1)
            SeriesDate   Value_1
3  2015-02-26 12:00:00  0.310326
4  2015-02-27 08:00:00  0.660795
5  2015-02-28 04:00:00  0.354475
6  2015-03-01 00:00:00  0.061312
7  2015-03-01 20:00:00  0.443908
8  2015-03-02 16:00:00  0.708326
9  2015-03-03 12:00:00  0.257419
10 2015-03-04 08:00:00  0.618363
11 2015-03-05 04:00:00  0.121625
12 2015-03-06 00:00:00  0.637324
13 2015-03-06 20:00:00  0.058292
14 2015-03-07 16:00:00  0.047624

另一种选择是使用max,谢谢Pocin

cutoff_date = df["SeriesDate"].max() - pd.Timedelta(days=days)
print (cutoff_date)
2015-02-25 16:00:00

如果您只想按dates 过滤:

days=10    
cutoff_date = df["SeriesDate"].dt.date.iloc[-1] - pd.Timedelta(days=days)
print (cutoff_date)
2015-02-25

编辑:

您可以使用dayofweek 过滤掉周末的日期,然后使用isin

start = pd.to_datetime('2015-02-24')
rng = pd.date_range(start, periods=15)
df = pd.DataFrame({'SeriesDate': rng, 'Value_1': np.random.random(15)})  
print (df)
   SeriesDate   Value_1
0  2015-02-24  0.498387
1  2015-02-25  0.435767
2  2015-02-26  0.299233
3  2015-02-27  0.489286
4  2015-02-28  0.892167
5  2015-03-01  0.507436
6  2015-03-02  0.360427
7  2015-03-03  0.903886
8  2015-03-04  0.718148
9  2015-03-05  0.645489
10 2015-03-06  0.251285
11 2015-03-07  0.139275
12 2015-03-08  0.756845
13 2015-03-09  0.565863
14 2015-03-10  0.148077
days=10    
last_day = df["SeriesDate"].dt.date.iloc[-1]
cutoff_date = last_day - pd.Timedelta(days=days)
rng = pd.date_range(cutoff_date, last_day)

rng = rng[(rng.dayofweek != 0) & (rng.dayofweek != 6)]
print (rng)
DatetimeIndex(['2015-02-28', '2015-03-03', '2015-03-04', '2015-03-05',
               '2015-03-06', '2015-03-07', '2015-03-10'],
              dtype='datetime64[ns]', freq=None)

df1 = df[df['SeriesDate'].isin(rng)]
print (df1)
   SeriesDate   Value_1
4  2015-02-28  0.892167
7  2015-03-03  0.903886
8  2015-03-04  0.718148
9  2015-03-05  0.645489
10 2015-03-06  0.251285
11 2015-03-07  0.139275
14 2015-03-10  0.148077

【讨论】:

  • 而不是依赖日期时间索引进行排序并使用iloc[-1],使用df['SeriesDate'].max() 可能是可行的替代方案
  • 谢谢两位,是否有可能到达 cutoff_date 以便它忽略周末日期?也就是说,如果 days = 10,则 cutoff_date 是前 10 天的日期,忽略周末。这仅包括工作日。
猜你喜欢
  • 2014-05-18
  • 1970-01-01
  • 1970-01-01
  • 2023-02-06
  • 2019-04-29
  • 2017-07-27
相关资源
最近更新 更多