У меня есть данные за 1 год, которые представляют собой почасовые данные временных рядов, поэтому между ними отсутствует несколько временных меток. Форма этих данных: (8188, 3) образец данных, который я прикрепил ниже.
Я выполняю повторную выборку временных меток в соответствии с продолжительностью моих данных, что приведет к созданию всех временных меток за один год, даже которые отсутствовали в моих исходных данных df_hourly = temp_df.resample('h').asfreq() форма повторной выборки индекса: (8764, 1)
Теперь я беру разницу между повторной выборкой данных и исходными данными new_rows = df_hourly.index.difference(original_index), поэтому фактическая форма индекса должна иметь вид (8764-8188 = 576), а затем я заменю эти 576 отсутствующих временных меток медианой общего числа.
temp_df = temp_df[temp_df['cell'] == cell]
print(temp_df.head())
temp_df.to_csv('temp_df.csv')
print(temp_df.shape)
# get_missing_duplicates(temp_df)
# fill_missing_duplicates()
print(temp_df.shape)
temp_df['_time'] = pd.to_datetime(temp_df['_time'])
print(temp_df['_time'].dtype)
temp_df.set_index('_time', inplace=True)
original_index = temp_df.index
print(original_index)
print("original_index",original_index.shape)
df_hourly = temp_df.resample('h').asfreq()
print(df_hourly)
# This line is not working as expected
new_rows = df_hourly.index.difference(original_index)
print("&&&&&&&&&&&&",original_index)
median_value = df['Total'].median()
# new_rows = df_hourly.index.difference(temp_df.index)
print("new_rows",new_rows)
new_rows = df_hourly.index.difference(original_index) эта строка дает неправильный результат, в основном она должна возвращать разницу df_hourly.index и
Результат temp_df.index:
DatetimeIndex(['2023-05-22 02:00:04+00:00', '2023-05-22 03:00:03+00:00',
'2023-05-22 04:00:03+00:00', '2023-05-22 05:00:03+00:00',
'2023-05-22 06:00:03+00:00', '2023-05-22 07:00:03+00:00',
'2023-05-22 08:00:03+00:00', '2023-05-22 09:00:03+00:00',
'2023-05-22 10:00:03+00:00', '2023-05-22 11:00:03+00:00',
...
'2024-05-20 17:00:03+00:00', '2024-05-20 18:00:04+00:00',
'2024-05-20 20:00:03+00:00', '2024-05-20 21:00:03+00:00',
'2024-05-20 22:00:03+00:00', '2024-05-20 23:00:03+00:00',
'2024-05-21 01:00:03+00:00', '2024-05-21 02:00:03+00:00',
'2024-05-21 04:00:03+00:00', '2024-05-21 05:00:03+00:00'],
dtype='datetime64[ns, UTC]', name='_time', length=8188, freq=None)
Результат df_hourly.index:
df_hourly_index RangeIndex(start=0, stop=8764, step=1)
(8764, 3)
Образец данных:






Хотя я еще не совсем понял проблему, и, как уже упоминалось, некоторые примеры строк, а также распечатки ошибок будут полезны.
Но я думаю, нам нужно использовать temp_df['Total'].median() вместо df['Total'].median().
Кроме того, кажется, что здесь много избыточности.
temp_df.reset_index(inplace=True)
temp_df['_time'] = pd.to_datetime(temp_df['_time'], utc=True)
# Filtering by cell if needed
cell = 'A'
temp_df = temp_df[temp_df['cell'] == cell]
# Ensuring '_time' is the index and sorted
temp_df.set_index('_time', inplace=True)
temp_df = temp_df.sort_index()
# Saving the original index
original_index = temp_df.index
# Resample the data to get all hourly timestamps
df_hourly = temp_df.resample('H').asfreq()
# Calculate the median value for filling
median_value = temp_df['Total'].median()
# Identify the missing timestamps
new_rows = df_hourly.index.difference(original_index)
# Fill in the missing timestamps with the median value
df_hourly.loc[new_rows, 'Total'] = median_value
# Reset the index if needed
df_hourly.reset_index(inplace=True)
# Save the result
df_hourly.to_csv('df_hourly.csv')
print("Original DataFrame shape:", temp_df.shape)
print("Resampled DataFrame shape:", df_hourly.shape)
print("Missing timestamps shape:", new_rows.shape)
print(df_hourly.head(10))
Original DataFrame shape: (16376, 2)
Resampled DataFrame shape: (8190, 3)
Missing timestamps shape: (2,)
_time cell Total
0 2023-05-22 00:00:00+00:00 A 0.0
1 2023-05-22 01:00:00+00:00 A 1.0
2 2023-05-22 02:00:00+00:00 A 2.0
3 2023-05-22 03:00:00+00:00 A 3.0
4 2023-05-22 04:00:00+00:00 A 4.0
5 2023-05-22 05:00:00+00:00 A 5.0
6 2023-05-22 06:00:00+00:00 A 6.0
7 2023-05-22 07:00:00+00:00 A 7.0
8 2023-05-22 08:00:00+00:00 A 8.0
9 2023-05-22 09:00:00+00:00 A 9.0
new_rows = df_hourly.index.difference(original_index) в основном эта строка работает неправильно.
pandas 2.2.1
Проблема не в упомянутой вами строке кода, а в ваших данных. Если вы посмотрите на свои значения времени, то увидите, что через целый час прошло несколько секунд, прежде чем была сделана запись:
'2023-05-22 02:00:04+00:00' - 4 seconds after 2:00
'2023-05-22 03:00:03+00:00' - 3 seconds after 3:00
Ежечасная повторная выборка устраняет эти спорадические отклонения. Таким образом, вы получите разные индексы, которые могут вообще не перекрываться с исходными временными метками. Поэтому вам может потребоваться округлить время перед повторной выборкой, чтобы найти недостающие временные метки, например:
temp_df['_time'] = pd.to_datetime(temp_df['_time'], utc=True).dt.round('h')
В качестве альтернативы вы можете найти недостающие метки времени, подсчитав данные за каждый час. В вашем коде это может выглядеть так:
new_rows = df_hourly.index[temp_df.resample('h').size() == 0]
Если по какой-то причине нам нужно сохранить исходные временные метки, то я думаю, что asfreq() может быть не лучшим выбором; использование first() выглядит более разумным. Также я бы добавил в этом случае некоторое отрицательное смещение при повторной выборке, на тот случай, если некоторые записи были сделаны за несколько секунд до окончания часа, примерно так:
df_hourly = temp_df.resample('h', offset=pd.Timedelta('-5min')).first()
Если причина поиска разницы между временными метками, подвергнутыми повторной выборке, и исходными состоит в заполнении пробелов, вместо этого мы можем использовать fillna(...).
Следующий пример данных был взят из исходного сообщения с одним изменением, чтобы представить возможную проблему (см. «За секунду до…» в коде и понятие о параметре offset= для resample):
import pandas as pd
timestamps = [
'2024-05-20 17:00:03+00:00',
'2024-05-20 18:00:04+00:00',
# missing
'2024-05-20 20:00:03+00:00',
'2024-05-20 20:59:59+00:00', # a second before 21:00:00
'2024-05-20 22:00:03+00:00',
'2024-05-20 23:00:03+00:00',
# missing
'2024-05-21 01:00:03+00:00',
'2024-05-21 02:00:03+00:00',
# missing
'2024-05-21 04:00:03+00:00',
'2024-05-21 05:00:03+00:00'
]
values = [403, 369, 375, 394, 398, 372, 335, 385, 415, 383]
df = pd.DataFrame({
'time': pd.to_datetime(timestamps, utc=True),
'value': values}
)
Вариант 1. Сохраните исходные временные метки (без округления).
five_min = pd.Timedelta('5min')
grouped_by_hour = df.set_index('time').resample('h', offset=-five_min)
resampled_data = grouped_by_hour.first()
is_new_record = grouped_by_hour.size() == 0
resampled_data.loc[is_new_record, 'value'] = round(df['value'].median())
resampled_data['value'] = resampled_data.astype({'value': int})
resampled_data.index += five_min
print('Resampled_data'.upper(),
resampled_data,
'\nNew records'.upper(),
resampled_data.index[is_new_record],
sep='\n')
Вариант 2. Перед повторной выборкой округлите временные метки до ближайшего часа.
rounded_original_time = df['time'].dt.round('h')
resampled_data = (
df[['value']]
.set_index(rounded_original_time)
.resample('h')
.asfreq()
)
new_records = resampled_data.index.difference(rounded_original_time)
resampled_data.loc[new_records, 'value'] = round(df['value'].median())
print('Resampled_data'.upper(),
resampled_data,
'\nNew records'.upper(),
new_records,
sep='\n')
Можете ли вы предоставить небольшой пример данных (несколько строк), в которых ваша проблема все еще возникает? Кроме того, необходимо предоставить только соответствующий код (например, все вызовы
plot()в вашем вопросе не нужны), чтобы люди могли его протестировать. Часто, пытаясь предоставить минимальный, воспроизводимый пример для StackOverflow, вы сами обнаруживаете и решаете проблему.