Временной фрейм данных с конечными начальными столбцами до 10-минутного диапазона Dataframe

#python #python-3.x #pandas #dataframe #timestamp

#python #python-3.x #pandas #фрейм данных #временная метка

Вопрос:

У меня есть фрейм данных, в котором время начала и окончания описания указано в столбцах. Описание находится в другом столбце.

Я пытаюсь преобразовать набор данных в фрейм данных с диапазоном 10 минут. В выходном фрейме данных выбираются начальная и конечная дата. Если данных нет, должен быть nan

В качестве примера:

 start_date = 15/09/2020 14:00:00
end_date = 16/09/2020 23:00:00
  

Фрейм данных данных

      start_time              end_time           info

15/09/2020 14:35:54       15/09/2020 15:05:48     A                
15/09/2020 15:54:05       16/09/2020 02:15:22     B 
16/09/2020 21:17:10       16/09/2020 22:15:04     A 
...
  

Тестовый фрейм данных

       timestamp          info

15/09/2020 14:00:00       nan   
15/09/2020 14:10:00       nan
15/09/2020 14:20:00       nan
15/09/2020 14:30:00       A
15/09/2020 14:40:00       A
15/09/2020 14:50:00       A
15/09/2020 15:00:00       A
15/09/2020 15:10:00       A
15/09/2020 15:20:00       nan
15/09/2020 15:30:00       nan
15/09/2020 15:40:00       nan
15/09/2020 15:50:00       B
15/09/2020 16:00:00       B
15/09/2020 16:10:00       B
15/09/2020 16:20:00       B
...
  

До сих пор я делал:

 data['timestampStart'] = pd.to_datetime(data['timestampStart'])
data['timestampEnd'] = pd.to_datetime(data['timestampEnd'])

range_time = pd.date_range(start=start_date, end=end_date, freq='10min')
test= pd.DataFrame()
test['timestamp'] = pd.to_datetime(range_time)

for index, row in data.iterrows():
    if test['timestamp'] > data['timestampStart'] amp; test['timestamp'] < data['timestampEnd']:
        test['description'] = data['description']
    else:
        test['description'] == np.nan
  

Я получаю ошибку в операторе if:
неподдерживаемые типы операндов для amp;: ‘Timestamp’ и ‘Timestamp’

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

Спасибо

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

1. Я думаю, что ваша ошибка возникает из-за того, что вам нужны круглые скобки вокруг нескольких условий. если (test[‘timestamp’] > data[‘timestampStart’]) amp; (test[‘timestamp’] < data[‘timestampEnd’]):

2. спасибо @yashar, но когда я применяю его, он возвращает: ValueError: можно сравнивать только объекты серии с одинаковыми метками

3. О, я понимаю. Это потому, что вы перебираете данные, а не тест, поэтому в каждом цикле он пытается сравнить весь столбец (серию) теста с одним значением в данных. У меня есть предложение, которое я включу в ответы.

Ответ №1:

Вы можете попробовать это:

 def check_date(s,d):
    if len(d[(d.timestampStart<s)amp;(d.timestampEnd>s)]) > 0:
        return d[(d.timestampStart<s)amp;(d.timestampEnd>s)].iloc[0]['info']
    else:
        return None

test['description'] = test.timestamp.apply(lambda x: check_date(x, data))
  

При этом будет использоваться каждая строка тестового фрейма данных, чтобы выяснить, есть ли какие-либо совпадающие значения, найденные в data dataframe. Это не очень элегантно, но, похоже, работает.

Обновление: метод 2

Вы можете изменить основной фрейм данных, чтобы достичь того, что вы ищете

 data['start_base'] = data.start_time.apply(lambda x: x.replace(minute=int(x.minute/10)*10, second=0))

data['timestamp'] = data.apply(lambda x: pd.date_range(start=x.start_base, end=x.end_time,freq='10min'), axis=1)

new_data = data[['timestamp','info']].explode('length')
  

По сути, мы записываем 10-минутные интервалы между каждой парой «начало» / «конец», а затем помещаем их в один столбец с помощью df.explode().
Затем вы можете объединить это с «тестовым» фреймом данных, чтобы получить все временные интервалы по своему усмотрению.

 test = test.merge(new_data, on='timestamp', how='left')
  

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

1. Спасибо, это работает. Однако он довольно медленный. Есть ли у вас какие-либо предложения о том, как его ускорить?

2. Я обновил ответ другим предложением, я думаю, это было бы намного быстрее. Проблема с первым решением заключается в том, что весь фрейм данных «данные» подается в каждую строку при применении. Как я уже упоминал, это было не очень элегантное решение. 🙂