#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 , я не могу использовать это решение 🙂