Частота повторной выборки Pandas на уровне индекса

В Pandas я хотел бы пересчитать свой фрейм данных и взять среднее значение за 5-часовой период и в пределах уровня индекса. Мой фрейм данных выглядит так: df

            timestamp       width  length
name                                    
10    2019-08-01 00:00:00   10.1    86.1
10    2019-08-01 00:00:10   10.0    86.2
10    2019-08-01 00:05:40   10.1    86.3
10    2019-08-01 00:05:50   10.0    86.2
8     2019-08-01 00:05:54   12.0   110.0

Я хотел бы сохранить свою переменную name в качестве индекса (желательно не устанавливать метку времени в качестве индекса), например:

            timestamp       width  length
name                                    
10    2019-08-01 00:00:05   10.05   86.15
10    2019-08-01 00:05:45   10.05   86.25
8     2019-08-01 00:05:54   12.0    110.0

Я пытался:

df_resample = df.resample('5H', on='timestamp').mean()

Но это не будет работать на уровне индекса. Также он устанавливает дату и время в индексе, которого я стараюсь избегать.


person Jeroen    schedule 26.02.2020    source источник


Ответы (2)


IIUC, вы можете использовать groupby и resample:

(df.groupby(level=0, sort=False)
   .resample('5min', on='timestamp').mean()
   .reset_index()
)

Однако это не усредняет ваши временные метки, поскольку вы не можете добавить тип Datetime в pandas, хотя есть способы обойти это.

   name           timestamp  width  length
0    10 2019-08-01 00:00:00  10.05   86.15
1    10 2019-08-01 00:05:00  10.05   86.25
2     8 2019-08-01 00:05:00  12.00  110.00

Обновить. Если вам нужна средняя метка времени, вы можете временно преобразовать метку времени в int, взяв среднее значение, и преобразовать обратно:

(df.assign(int_time=lambda x: x['timestamp'].astype('int64') )
   .groupby(level=0, sort=False)
   .resample('5min', on='timestamp').mean()
   .reset_index()
   .assign(timestamp=lambda x: x['int_time'].astype('int64').astype('datetime64[ns]'))
   .drop('int_time', axis=1)
)

Выход:

   name           timestamp  width  length
0    10 2019-08-01 00:00:05  10.05   86.15
1    10 2019-08-01 00:05:45  10.05   86.25
2     8 2019-08-01 00:05:54  12.00  110.00
person Quang Hoang    schedule 26.02.2020
comment
Спасибо за ваш ответ. Решение достаточно хорошее, желательно получить средние временные метки. - person Jeroen; 26.02.2020
comment
@Jeroen, как я уже сказал, есть способы обойти это. См. Обновленный ответ. - person Quang Hoang; 26.02.2020
comment
Решение выглядит неплохо. Однако при обратном преобразовании: я получаю сообщение об ошибке во второй последней строке: astype ('int64') ValueError: невозможно преобразовать неконечные значения (NA или inf) в целые числа. - person Jeroen; 26.02.2020
comment
Это означает, что у вас есть NaT время в timestamp. Вам нужно решить, что с ними делать. - person Quang Hoang; 26.02.2020
comment
У меня на самом деле 0 NaN в моей метке времени. Я проверил это: count_nan = len(df_area['timestamplast']) - df_area['timestamplast'].count() - person Jeroen; 27.02.2020
comment
Как насчет df_area['timestamplast'].isna().sum()? - person Quang Hoang; 27.02.2020
comment
Вы можете попробовать связать первый .astype('int64') с .astype('float64'), чтобы mean() не переполнялся. Если это не сработает, им жаль, что я не знаю. Если вы хотите, вы можете поделиться своими данными, и я могу посмотреть. - person Quang Hoang; 27.02.2020
comment
Спасибо за вашу помощь. Теперь он работает, пропустив: df['timestamp'] = df['timestamp'].dt.strftime('%Y-%m-%d-%H-%M-%s').astype('datetime64[s]'). Формат не требовался и распознавался автоматически. Весьма признателен! - person Jeroen; 28.02.2020

Временно установите метку времени в качестве индекса, затем восстановите исходный индекс.

df = df.reset_index().set_index('timestamp').resample('5H').mean().set_index('name')

Это то, что вы хотели получить?

person Oleg O    schedule 26.02.2020
comment
Спасибо за ваш ответ. Это также среднее значение для моего исходного индекса, который иногда мне не нужен. Установив для индекса имя, он удаляет дату и время, что также нежелательно. - person Jeroen; 26.02.2020
comment
Итак, не усредняйте свой индекс. Вы можете создать объект ресамплера, подобный этому res_obj = df.reset_index().set_index('timestamp').resample('5H'), затем создать отдельные таблицы с отдельными функциями, а затем присоединиться, то есть df_mean = res_obj[some_columns].mean() df_last = res_obj[['name']].last() df = pd.concat([df_mean, df_last], axis=1).reset_index().set_index('name') - person Oleg O; 26.02.2020