Вставить данные и условия на отметку времени - Pandas Python - PullRequest
0 голосов
/ 02 апреля 2020

Столбец Flag соответствует появлению тревоги с началом и концом с соответствующим столбцом отметки времени.

Правило: Каждое начало и следующий конец должны быть в одну и ту же дату !

У меня есть этот фрагмент данных:

   Flag                     Timestamp
1  begin   2019-10-25 09:39:39.914889
2  end     2019-10-25 09:41:09.103102
3  begin   2019-10-25 10:39:58.352073
4  end     2019-10-25 10:40:06.266782
5  begin   2019-10-25 16:35:22.485574
6  end     2019-10-27 09:50:31.713192
7  begin   2019-10-29 14:04:33.095633
8  end     2019-10-29 14:05:07.639344
9  begin   2019-10-29 14:13:07.924966
10 end     2019-10-29 14:13:08.888890

В строке 5 у меня начало с даты 2019-10-25 и конец с датой 2019-10- 27, так что это проблема.

Итак, у меня есть решение, но я не могу его реализовать из-за недостатка опыта в pandas python.

Соблюдать правило 1 Я хотел бы реализовать 2 процедуры:

  • добавить отсутствующие даты ТОЛЬКО в этом конкретном c случае
  • добавить время открытия и закрытия * ТОЛЬКО в этом конкретном c случае

указанном c случае: превышение начала и конца тревоги в течение нескольких дней.

В нашем примере:

  Flag                 Timestamp
  begin   2019-10-26 07:00:00.00  
  end     2019-10-26 17:00:00.00

и

  Flag                 Timestamp
  end     2019-10-25 17:00:00.00
  begin   2019-10-27 07:00:00.00

результат должен быть:

   Flag                     Timestamp
1  begin   2019-10-25 09:39:39.914889
2  end     2019-10-25 09:41:09.103102
3  begin   2019-10-25 10:39:58.352073
4  end     2019-10-25 10:40:06.266782
5  begin   2019-10-25 16:35:22.485574
6  end     2019-10-25 17:00:00.000000
7  begin   2019-10-26 07:00:00.000000 
8  end     2019-10-26 17:00:00.000000
9  begin   2019-10-27 07:00:00.000000
10 end     2019-10-27 09:50:31.713192
11 begin   2019-10-29 14:04:33.095633
12 end     2019-10-29 14:05:07.639344
13 begin   2019-10-29 14:13:07.924966
14 end     2019-10-29 14:13:08.888890

спасибо за ваше терпение и ваше время!

1 Ответ

0 голосов
/ 02 апреля 2020

Вы можете попробовать следующее:

  • Сгруппировать кадр данных по 2 строкам. В этом обсуждении объясняется, как.

  • Для каждой группы: мы проверяем, что даты совпадают.

    • Длина в группе сообщите нам
    • Если две даты совпадают (например, len() == 1)
      • Возвращает две даты
    • Остальное:
      • Мы генерируем daterange от даты начала и окончания.
      • Мы дублируем каждое значение с помощью repeat
      • Удаляем первый элемент и последний, используя iloc
      • Поскольку repeat дублирует значения, мы сбрасываем индекс, используя reset_index
      • Тогда мы меняем тип на pd.Timestamp
      • Для всех этих дат, и поскольку мы просто преобразовали их в pd.Timestamp, теперь мы можем использовать pd.Timestamp.replace метод установки часов (8 или 17).
      • Наконец мы добавляем дату min и max в наш список и возвращаем целое.

Код

# Timestamp type
df["Timestamp"] = pd.to_datetime(df["Timestamp"])
# print(df)
#      Flag                  Timestamp
# 1   begin 2019-10-25 09:39:39.914889
# 2     end 2019-10-25 09:41:09.103102
# 3   begin 2019-10-25 10:39:58.352073
# 4     end 2019-10-25 10:40:06.266782
# 5   begin 2019-10-25 16:35:22.485574
# 6     end 2019-10-27 09:50:31.713192
# 7   begin 2019-10-26 16:35:22.485574
# 8     end 2019-10-27 09:50:31.713192
# 9   begin 2019-10-29 14:04:33.095633
# 10    end 2019-10-29 14:05:07.639344
# 11  begin 2019-10-29 14:13:07.924966
# 12    end 2019-10-29 14:13:08.888890


# Our function
def extends_dates(x):
    if len(x.groupby(x.Timestamp.dt.date)) == 1:
        return x.Timestamp
    else:
        # Create daterange
        d_range = pd.date_range(start=x.Timestamp.dt.date.min(), end=x.Timestamp.dt.date.max()) \
            .repeat(2) \
            .to_series() \
            .iloc[1:-1] \
            .reset_index(drop=True) \
            .apply(pd.Timestamp)
        # Set hours of all date
        news = [d.replace(hour=17) if i % 2 == 0 else d.replace(hour=8)
                for i, d in enumerate(d_range)]
        # Add min (from dataframe)
        news.insert(0, min(x.Timestamp))
        # Add max date (from dataframe)
        news.append(max(x.Timestamp))
        return pd.Series(news, name="Timestamp")

print(df)
# Timestamp type
df["Timestamp"] = pd.to_datetime(df["Timestamp"])

# Starting index to 0
df.index -= 1

# Create a dataframe from the series
out = df.groupby(df.index // 2).apply(extends_dates).reset_index(drop=True).to_frame()
print(out)
#                     Timestamp
# 0  2019-10-25 09:39:39.914889
# 1  2019-10-25 09:41:09.103102
# 2  2019-10-25 10:39:58.352073
# 3  2019-10-25 10:40:06.266782
# 4  2019-10-25 16:35:22.485574
# 5  2019-10-25 17:00:00.000000
# 6  2019-10-26 08:00:00.000000
# 7  2019-10-26 17:00:00.000000
# 8  2019-10-27 08:00:00.000000
# 9  2019-10-27 09:50:31.713192
# 10 2019-10-26 16:35:22.485574
# 11 2019-10-26 17:00:00.000000
# 12 2019-10-27 08:00:00.000000
# 13 2019-10-27 09:50:31.713192
# 14 2019-10-29 14:04:33.095633
# 15 2019-10-29 14:05:07.639344
# 16 2019-10-29 14:13:07.924966
# 17 2019-10-29 14:13:08.888890

Я позволю вам перестроить столбец flag, используя, например, np.where .

Код :

import numpy as np
out["Flag"] = np.where(out.index % 2 == 0, "begin", "end")
print(out)
#                     Timestamp   Flag
# 0  2019-10-25 09:39:39.914889  begin
# 1  2019-10-25 09:41:09.103102    end
# 2  2019-10-25 10:39:58.352073  begin
# 3  2019-10-25 10:40:06.266782    end
# 4  2019-10-25 16:35:22.485574  begin
# 5  2019-10-25 17:00:00.000000    end
# 6  2019-10-26 08:00:00.000000  begin
# 7  2019-10-26 17:00:00.000000    end
# 8  2019-10-27 08:00:00.000000  begin
# 9  2019-10-27 09:50:31.713192    end
# 10 2019-10-26 16:35:22.485574  begin
# 11 2019-10-26 17:00:00.000000    end
# 12 2019-10-27 08:00:00.000000  begin
# 13 2019-10-27 09:50:31.713192    end
# 14 2019-10-29 14:04:33.095633  begin
# 15 2019-10-29 14:05:07.639344    end
# 16 2019-10-29 14:13:07.924966  begin
# 17 2019-10-29 14:13:08.888890    end

Редактировать 1

Запуск его два раза не меняет выход .

# 
# Timestamp type
df["Timestamp"] = pd.to_datetime(df["Timestamp"])

# Starting index to 0
df.index -= 1

# Create a dataframe from the series
out = df.groupby(df.index // 2).apply(extends_dates).reset_index(drop=True).to_frame()

out_2 = out.groupby(out.index // 2).apply(extends_dates).reset_index(drop=True).to_frame()
print(out == out_2)
#     Timestamp
# 0        True
# 1        True
# 2        True
# 3        True
# 4        True
# 5        True
# 6        True
# 7        True
# 8        True
# 9        True
# 10       True
# 11       True
# 12       True
# 13       True
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...