Python 如何找到从开始日期算起整整一年的数据帧的平均值?

Python 如何找到从开始日期算起整整一年的数据帧的平均值?,python,pandas,dataframe,Python,Pandas,Dataframe,我想找到基于第一个datetime索引的数据集的年平均值。 假设以下数据帧: Date/Time speed 2015-03-21 14:00:00 11.256 2015-03-21 14:10:00 13.789 2015-03-21 14:20:00 16.297 2015-03-21 14:30:00 11.259 ...

我想找到基于第一个datetime索引的数据集的年平均值。 假设以下数据帧:

    Date/Time                 speed       
2015-03-21 14:00:00           11.256
2015-03-21 14:10:00           13.789
2015-03-21 14:20:00           16.297
2015-03-21 14:30:00           11.259
...                              ...
2018-03-21 14:00:00            8.211
2018-03-21 14:10:00            5.324
2018-03-21 14:20:00            5.316
2018-03-21 14:30:00            2.982
我试图实现的是找到以下数据的平均值

  • 2015-03-21 14:00:002016-03-21 13:50:00
  • 2016-03-21 14:00:002017-03-21 13:50:00
  • 2017-03-21 14:00:002018-03-21 13:50:00
我熟悉使用熊猫按年份分组,但它没有给我想要的结果。另一种解决方案是手动对数据帧进行切片,但如果数据帧包含10年的数据,这将非常耗时


Pandas(或任何其他库)中是否有内置的方法来执行此操作?

闰年有问题,因此无法使用重采样或
时间增量
,最简单的方法是按最小年和最大年进行循环,并查看f字符串:

np.random.seed(2019)

rng = pd.date_range('2015-03-21 14:00:00', '2018-03-21 14:30:00', freq='10T')
df = pd.DataFrame({'speed':np.random.randint(1000, size=len(rng))}, index=rng)
#print (df)


out = pd.Series({x: df.loc[f'{x}-03-21 14:00:00':f'{x+1}-03-21 13:50:00', 'speed'].mean()
                   for x in range(df.index.year.min(), df.index.year.max()+1)})
print (out)
2015    501.062879
2016    498.546385
2017    498.490963
2018    580.250000
dtype: float64
另一个解决方案更为复杂,但也能很好地处理闰年问题——这个想法是每年分成两部分——在thresh datetime之前和之后,然后相加

#datetime for thresh - always need leeap year like 2000
date = pd.Timestamp('2000-03-21 14:00:00')
#replace all years to 2000 and test data fr matched conditions
mask = pd.to_datetime(df.index.strftime('2000-%m-%d %H:%M:%S')) < date
arr = np.where(mask, 'matched','nonmatched')

#sum of means have no sense, so need working mean = sum/count
df1 = df.groupby([arr, df.index.year])['speed'].agg(['sum','size'])
print (df1)
                      sum   size
matched    2016   5811589  11604
           2017   5725034  11460
           2018   5702078  11460
nonmatched 2015  20596429  41100
           2016  20478564  41100
           2017  20498607  41100
           2018      2321      4

要选择带有日期时间索引的数据帧的时间戳,请使用
df.loc

start = df.index[0]
dt = pd.Timedelta(1, unit="Y")
first_year_mean = df.loc[start:start+dt].mean()

一种方法是使用
pandas.DataFrame.resample
loffset
参数

deltaTime = datetime.datetime(2015,3,21,14) - datetime.datetime(2015,1,1)
resampled_df = df.resample('Y', loffset=deltaTime).mean()

这种方法唯一的缺点是它不会调整闰年的时间差。如果这对您来说不是很重要,那么这可能是一个很好的方法。

您是否尝试过抵消重采样以匹配您的时间段?您可以使用一个
loffset
参数。@NeillHerbst您可以帮我解决
loffset
参数的问题吗。我浏览了文档,最后写了这个
means=df.resample('1Y',loffset=datetime.timedelta(days=-21,weeks=-12,hours=-14)).mean()。我在这里做错了什么?我补充了一个答案。它应该是有效的,但你会发现它并不能解释闰年。这可能是该方法唯一的主要缺点。我想检查是否有任何库已经内置了此功能,我想我将根据您的答案编写一个更通用的函数。@Tabbakhh-添加了另一个同样适用于闰年的解决方案,请检查编辑后的答案。我在另一个数据集上测试了您的代码,结果非常接近正确答案!您代码的结果如下:
2015:8.177520 2016:8.756599
,而正确的结果(手动计算)如下:
2015:8.232503,2016:8.756599
。我目前正在努力找出为什么第一年的平均数不正确(与第二年不同)@Tabbakhh您如何手动计算?你能接受闰年吗?第一种解决方案非常有效,但第二种方案仅适用于第一年。我会接受第一个解决方案,因为它的工作,但我不确定第二个。万分感谢!什么不起作用?它是否抛出错误(如果是,请在此处报告),或者它没有提供所需的结果?它没有提供所需的结果。如果我的df从2015-03-21 14:00:00开始,你的代码取2015-03-21 14:00:00和2016-03-20 19:49:12之间的平均值(我从运行你的代码中得到的),而期望的结果是2015-03-21 14:00:00和2016-03-21 13:50:00之间的平均值不是我预期的,而是
pd.Timedelta(1,“Y”)
收益率
Timedelta('365天05:49:12'))
。。。您可以使用
pd.Timedelta(365,“d”)
pd.Timedelta(366,“d”)
取决于年份:)
pd.Timedelta(1,“Y”)
does yild to
Timedelta('365天05:49:12')
,将其添加到开始日期,您将得到**2016-03-20 19:49:12**。我想要一个库,它将自动处理每年的天数,而不是手动更改代码测试,但没有产生正确的结果。我得到的结果与运行
resampled\u df=df.resample('Y').mean()
而不运行
loffset
得到的结果相同。
deltaTime = datetime.datetime(2015,3,21,14) - datetime.datetime(2015,1,1)
resampled_df = df.resample('Y', loffset=deltaTime).mean()