Преобразовать интервалы в DateTimes - PullRequest
0 голосов
/ 07 сентября 2018

У меня есть DataFrame, который содержит интервалы, в которые был активен определенный датчик:

                 start                 end
0  2018-06-01 08:55:10 2018-06-01 09:01:00
1  2018-06-01 09:02:20 2018-06-01 09:04:55
2  2018-06-01 09:11:35 2018-06-01 09:23:44

Я бы хотел провести анализ временных рядов по этим данным. Для этого я хочу преобразовать эти данные в правильный временной ряд, имеющий временные метки каждые X минуты. Вот пример с X = 5 min:

                 time active
0 2018-06-01 08:55:10      1
1 2018-06-01 09:00:10      1
2 2018-06-01 09:05:10      0
3 2018-06-01 09:10:10      1

Вы можете прочитать выше как "active == 1, если датчик был активен в интервале [t, t+X]".

Обратите внимание, что интервалы не всегда не пересекаются.

В данный момент я конвертирую интервалы в DatetimeIndex с частотой X мин. После этого я снова пересматриваю серию (приходится на перекрывающиеся интервалы):

indices = []
for _, row in df.iterrows():
    indices.append(pd.date_range(row['start'], row['end'], freq='5T'))
index = indices[0].append(indices[1:])
series = pd.Series(np.ones(len(index), dtype=bool), index=index)
series = series.resample('5T').max().fillna(0)

Мой набор данных содержит около 15 миллионов записей. Вышеуказанное требует довольно много времени для запуска. Я хотел бы сделать это более производительным.

У кого-нибудь есть хорошая идея?

1 Ответ

0 голосов
/ 07 сентября 2018

Если интервалы не пересекаются и строки сортируются (при условии, что один датчик и последовательные данные), как в вашем примере, вы можете сделать простой цикл и проверять строку за строкой.

Пример:

import pandas as pd
import numpy as np

# Create your dataframe
x = np.array([
    ['2018-06-01 08:55:10', '2018-06-01 09:01:00'],
    ['2018-06-01 09:02:20', '2018-06-01 09:04:55'],
    ['2018-06-01 09:11:35', '2018-06-01 09:23:44']
    ])

df = pd.DataFrame(x, columns=['start', 'end'])
df['start'] = pd.to_datetime(df['start'])
df['end'] = pd.to_datetime(df['end'])
print(df)

Dataframe:

     start                 end
0 2018-06-01 08:55:10 2018-06-01 09:01:00
1 2018-06-01 09:02:20 2018-06-01 09:04:55
2 2018-06-01 09:11:35 2018-06-01 09:23:44

Код для генерации результатов:

results = []
interval = pd.Timedelta('5 minutes') # interval X
start = pd.to_datetime('2018-06-01 08:55:10')

time = start
# iterate each sensor interval
# must be sorted by time, and no intervals should overlap
for (i, row) in df.iterrows():
    # go to the next interval when time is after current interval
    while time < row['end']:
        if time >= row['start']:
            results.append([time, 1])
        else:
            results.append([time, 0])
        time += interval

result_df = pd.DataFrame(results, columns=['time', 'active'])
result_df['time'] = pd.to_datetime(result_df['time'])
print(result_df)

Результат:

                 time  active
0 2018-06-01 08:55:10       1
1 2018-06-01 09:00:10       1
2 2018-06-01 09:05:10       0
3 2018-06-01 09:10:10       0
4 2018-06-01 09:15:10       1
5 2018-06-01 09:20:10       1

Это займет несколько секунд для 15-метровых рядов.

...