Вычисление максимального итога за период времени, когда значения увеличиваются и уменьшаются

#python #mysql #sql #pandas #numpy

#python #mysql #sql #pandas #numpy

Вопрос:

У меня есть ситуация, когда мне нужно рассчитать общее количество клиентов за день из фрейма данных, где значения увеличиваются и уменьшаются. Но вот в чем загвоздка:

Если у меня есть фрейм данных, например

 DATETIME                CLIENTS
2018-03-03 08:00:00     1
2018-03-03 09:00:00     2
2018-03-03 10:00:00     3
2018-03-03 11:00:00     4
2018-03-03 12:00:00     5
2018-03-03 13:00:00     3
2018-03-03 14:00:00     4
2018-03-03 15:00:00     5
  

Максимальное общее количество клиентов за этот день 7 связано с тем, что оно увеличивается до 5 at 12:00:00 , затем значение уменьшается в течение следующего часа, но мы не вычитаем из 5 , а затем оно увеличивается до 4 at 14:00:00 , поэтому мы ДОБАВЛЯЕМ 1 , и 5 в 15:00:00 so мы ДОБАВЛЯЕМ еще 1 один, так что в общей сложности в 7 течение дня максимальное количество клиентов.

Я пробовал cumsum() и MAX(), поскольку думал, что они будут полезны, но, увы…

Мне нужно реализовать это либо в SQL, либо в Python. Был бы признателен за любую помощь!

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

1. А? Почему не ответ «7»? Что, если второе общее количество увеличилось только до 4? Или до 7? Или если оно уменьшилось и достигло максимума в три раза? Ваше объяснение не полностью объясняет логику.

2. разве всего не 7 клиентов? в 13.00 осталось 2, а позже прибывает 2…

3. Извинения! Вы оба правы! Я отредактирую

Ответ №1:

Ваша логика заключается в том, что вы хотите подсчитывать только входящих посетителей, а не уходящих. Теперь, если вы берете diff() , то входящие положительные, а уходящие отрицательные. Таким образом, мы можем просто замаскировать отрицательное 0 значение и снова суммировать.

Давайте попробуем:

 dates = df.DATETIME.dt.normalize()

max_visitors = (df.groupby(dates)['CLIENTS'].diff()  # find the difference
                  .fillna(df['CLIENTS'])             # these are the first records in the day
                  .clip(0)                           # replace negatives with 0
                  .groupby(dates).sum()              # sum by days
               )
  

Вывод:

 DATETIME
2018-03-03    7.0
Name: CLIENTS, dtype: float64
  

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

1. Хороший! Спасибо!

Ответ №2:

Если ваша версия MySQL 8.0 , вы можете использовать LAG() функцию окна и агрегацию:

 select
  sum(case when clients > prev then clients - prev end) total
from (
  select *, lag(clients, 1, 0) over (order by datetime) prev
  from tablename
  where date(datetime) = '2018-03-03'
) t
  

Смотрите демонстрацию.

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

1. Плюс 1, поскольку я уверен, что это кому-то поможет, но поскольку я не использую MySQL 8.0 , я не могу использовать это решение 🙂