Измените фрейм данных в зависимости от соответствия datetimeindex массиву datetime

#python #pandas #dataframe #datetime #indexing

Вопрос:

У меня есть длинный фрейм данных с индексом datetimeindex, который запускается каждые 5 минут. Однако есть пробелы, а иногда индексы выпадают из шаблона (через 3 минуты после предыдущей строки, в то время как должно быть 5 минут). Я сгенерировал массив со значениями даты и времени по одному и тому же шаблону. Я хотел бы изменить свой фрейм данных, удалив каждую строку, если ее индекса нет в массиве datetime, и создав пустую строку NaN для каждого отсутствующего индекса datetimeindex. Как я мог бы это сделать без цикла for ?

Ожидаемые Результаты: как преобразовать df в df2

Пример кода, показывающий, что я хотел бы получить в итоге. df2 представляет исправленный df, в котором строки с индексами из шаблона 5 минут (12 минут, 27 минут) удалены, а отсутствующая строка 25 минут добавлена и заполнена nan.

 import pandas as pd
import matplotlib.dates as mdates
import numpy as np
from datetime import datetime

# Create random data
varr1 = np.random.rand(6)
varr2 = np.random.rand(6)

#create the faulty datetimeindex
time_str1 = '23/9/2021 11:10'
date_format_str1 = '%d/%m/%Y %H:%M'
time_str2 = '23/9/2021 11:12'
time_str3 = '23/9/2021 11:15'
time_str4 = '23/9/2021 11:20'
time_str5 = '23/9/2021 11:27'
time_str6 = '23/9/2021 11:30'

# DataFrame with faulty index (some rows do not follow the 5min delta rule, and the 25min mark is missing)
df_time = []
df_time.append(datetime.strptime(time_str1, date_format_str1))
df_time.append(datetime.strptime(time_str2, date_format_str1))
df_time.append(datetime.strptime(time_str3, date_format_str1))
df_time.append(datetime.strptime(time_str4, date_format_str1))
df_time.append(datetime.strptime(time_str5, date_format_str1))
df_time.append(datetime.strptime(time_str6, date_format_str1))


df = pd.DataFrame(index=df_time)
df['var1'] = varr1
df['var2'] = varr2

# Function to generate an array of datetime
def perdelta(start, end, delta):
    curr = start
    while curr < end:
        yield curr
        curr  = delta
date_arr= []

# Generate datetime that will serve as model
for result in perdelta(df.index[0], df.index[-1], dt.timedelta(minutes=5)):       
    date_arr.append(result) 
date_arr.append(datetime.strptime(time_str6, date_format_str1))

# DataFrame that I want, rows with missing index from datetime array added and filled with NaNs, and the ones falling out of the 5min pattern dropped
df2 = pd.DataFrame({'var1': [varr1[0], varr1[2], varr1[3], np.nan, varr1[-1]], 'var2': [varr2[0], varr2[2], varr2[3], np.nan, varr2[-1]]},index=date_arr)
 

Комментарии:

1. можете ли вы добавить свой ожидаемый выходной кадр данных. Было бы удобно создать небольшой образец фрейма данных

2. пример кода, который я написал, дает вам ожидаемый результат. Я не знаю, как распечатать вывод в вопросе stackoverflow, поэтому я скопировал снимок экрана того, что я хочу: как преобразовать df в df2. Спасибо за ваши отзывы !

Ответ №1:

Вы можете попробовать приведенный ниже пример кода.

 
import pandas as pd
import numpy as np
from datetime import timedelta, datetime
varr1 = np.random.rand(6)
varr2 = np.random.rand(6)
date_format = '%d/%m/%Y %H:%M'
dates = ['23/9/2021 11:10',
         '23/9/2021 11:12',
         '23/9/2021 11:15',
         '23/9/2021 11:20',
         '23/9/2021 11:27',
         '23/9/2021 11:30']
indexes = [datetime.strptime(date, date_format) for date in dates]
df = pd.DataFrame({'var1': varr1, 'var2': varr2}, index=indexes)
expected_dates = []
cur = indexes[0]
end = indexes[-1]
while cur <= end:
    expected_dates.append(cur)
    cur  = timedelta(minutes=5)
items = []
for index in expected_dates:
    if index in df.index:
        item = {
            'var1': df.loc[index, 'var1'],
            'var2': df.loc[index, 'var2'],

        }
    else:
        item = {
            'var1': np.nan,
            'var2': np.nan
        }
    items.append(item)
df2 = pd.DataFrame(items, index=expected_dates)
df2

 

Это выход

введите описание изображения здесь