Как выполнить эту операцию SQL с помощью Python?

#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
 

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

1. Я не думаю, что это правильно — разве ОБЪЕДИНЕНИЕ не служит для выбора только первых значений none NaN для каждой группы?

2. @Grismar Не Coalesce заменяйте все нули указанным значением, в случае OP 0 .

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'])
 

Я написал это, наивно связывая необходимые операции воедино — возможно, удастся немного их оптимизировать.