Как найти среднее значение для Pandas DataFrame ровно через год с даты начала? - PullRequest
0 голосов
/ 20 февраля 2019

Я хотел бы найти среднегодовое значение набора данных на основе первого индекса даты и времени.Предположим, что следующий фрейм данных:

    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: 00 и 2016-03-21 13: 50: 00
  • 2016-03-21 14: 00: 00 и 2017-03-21 13: 50: 00
  • 2017-03-21 14: 00: 00 и 2018-03-21 13:50: 00

Я знаком с группировкой по годам, используя Pandas, но она не дает мне желаемых результатов.Другое решение состоит в том, чтобы вручную разрезать фрейм данных, но это займет очень много времени, если фрейм данных содержит данные за 10 лет.

Есть ли в Pandas встроенный метод (или, возможно, любая другая библиотека) для этого

Ответы [ 3 ]

0 голосов
/ 20 февраля 2019

Чтобы выбрать метки времени для DataFrame df с указателем даты и времени, используйте df.loc:

start = df.index[0]
dt = pd.Timedelta(1, unit="Y")
first_year_mean = df.loc[start:start+dt].mean()
0 голосов
/ 20 февраля 2019

Один из методов заключается в использовании параметра loffset, равного pandas.DataFrame.resample.

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

Единственным недостатком этого метода является то, что он не корректирует временную дельту для високосных лет.Если это не так важно для вас, то, вероятно, это хороший метод для подражания.

0 голосов
/ 20 февраля 2019

Существует проблема с високосными годами, поэтому повторная выборка или Timedelta невозможна, проще всего использовать цикл с диапазоном по минимальным и максимальным годам и выделением с помощью 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

Другое решениеболее сложный, но хорошо работающий с високосными годами - идея разбивается каждый год на 2 части - до даты и времени, а затем суммируется.

#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

#data before thresh datetime
matched = df1.loc['matched']
matched.index -= 1
print (matched)
          sum   size
2015  5811589  11604
2016  5725034  11460
2017  5702078  11460

#data after thresh
nonmatched = df1.loc['nonmatched']
print (nonmatched)
           sum   size
2015  20596429  41100
2016  20478564  41100
2017  20498607  41100
2018      2321      4

#sum both DataFrames and divide sum by counts for mean
df2 = matched.add(nonmatched, fill_value=0)
out = df2['sum'].div(df2['size'])
print (out)
2015    501.062879
2016    498.546385
2017    498.490963
2018    580.250000
dtype: float64
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...