#python #pandas #dataframe #pandas-groupby
Вопрос:
У меня есть операция sql:
SELECT
date,
type,
SUM(COALESCE(value, 0)) OVER (PARTITION BY date ORDER BY type) value
FROM my_df
Я знаю , что с этой СУММОЙ можно справиться groupby().sum()
, но я не понимаю, что должно быть для SUM(COALESCE(value, 0)) OVER (PARTITION BY date ORDER BY type)
Как это сделать с помощью Python?
Комментарии:
1. Вы можете попробовать использовать библиотеку pandasql.
Ответ №1:
Предположим, у вас есть фрейм данных как df
. SUM(COALESCE(value, 0)) OVER (PARTITION BY date ORDER BY type)
является ли функция окна SQL, которая примерно эквивалентна cumsum
функции в панд:
df.value = df.value.fillna(0) # == COALESCE(value, 0)
df['value'] = df.sort_values('type').groupby('date').value.cumsum() # == SUM(COALESCE(value, 0)) OVER (PARTITION BY date ORDER BY type)
df[['date', 'type', 'value']] # == SELECT ... FROM df
Комментарии:
2. @Grismar Не
Coalesce
заменяйте все нули указанным значением, в случае OP0
.3. Из документации по Transact-SQL: «Оценивает аргументы по порядку и возвращает текущее значение первого выражения, которое изначально не принимает значение NULL». — существуют ли различные реализации? docs.microsoft.com/en-us/sql/t-sql/language-elements/…
4. Вот, собственно, что это значит. Предположим , что у вас есть
coalesce(expr1, expr2, expr3, ...)
, он принимает первое ненулевое значение из всех выражений. Поэтому , когда вы это делаетеcoalesce(value, 0)
, если значение не равно нулю, результатом будет значение, если значение равно нулю, результат будет равен 0, так как это следующее ненулевое значение.5. Ах, я вижу, что неправильно истолковал, как будет работать ОБЪЕДИНЕНИЕ в контексте «ЗА», ура.
Ответ №2:
Примечание: этот ответ неверен, так как он предполагает, что COALESCE работает как оконная функция, чего не происходит. Тем не менее, я оставляю его здесь на случай, если кто-то все равно ищет именно этот ответ. ОП, вероятно, нуждается в том, что опубликовал @psidom.
Поскольку Transact-SQL выбирает первое ненулевое значение для каждой даты, при упорядочении строк для этой даты по типу (и выбирает 0, если нет ненулевых значений), это делает то же самое с использованием pandas
(я предполагаю, что вы используете, когда ссылаетесь на фрейм данных):
from pandas import DataFrame
data = [
# should result in 20 for this date, first that's not None once sorted
{'date':'2021-01-01', 'type':'a', 'value': None},
{'date':'2021-01-01', 'type':'c', 'value': 10},
{'date':'2021-01-01', 'type':'b', 'value': 20},
# should result in 10 for this date, only value
{'date':'2021-01-02', 'type':'a', 'value': 10},
# should result in 0 for this date, as there are no values that are not None
{'date':'2021-01-03', 'type':'a', 'value': None},
]
df = DataFrame(data)
print(df.iloc[
df.sort_values('type')
.groupby('date')
.apply(
lambda x: x['value'].first_valid_index()
).fillna(0).astype(int)
]['value'])
Я написал это, наивно связывая необходимые операции воедино — возможно, удастся немного их оптимизировать.