Pandas groupby дублирует группы при использовании apply дважды - PullRequest
2 голосов
/ 24 января 2020

Может ли pandas groupby использовать groupby.apply(func), а внутри func использовать другой экземпляр .apply() без дублирования и перезаписи данных?

В каком-то смысле использование .apply() является вложенным.

Python 3.7.3 pandas==0.25.1

import pandas as pd


def dummy_func_nested(row):
    row['new_col_2'] = row['value'] * -1
    return row


def dummy_func(df_group):
    df_group['new_col_1'] = None

    # apply dummy_func_nested
    df_group = df_group.apply(dummy_func_nested, axis=1)

    return df_group


def pandas_groupby():
    # initialize data
    df = pd.DataFrame([
        {'country': 'US', 'value': 100.00, 'id': 'a'},
        {'country': 'US', 'value': 95.00, 'id': 'b'},
        {'country': 'CA', 'value': 56.00, 'id': 'y'},
        {'country': 'CA', 'value': 40.00, 'id': 'z'},
    ])

    # group by country and apply first dummy_func
    new_df = df.groupby('country').apply(dummy_func)

    # new_df and df should have the same list of countries
    assert new_df['country'].tolist() == df['country'].tolist()
    print(df)


if __name__ == '__main__':
    pandas_groupby()

Приведенный выше код должен вернуть

  country  value id new_col_1  new_col_2
0      US  100.0  a      None     -100.0
1      US   95.0  b      None      -95.0
2      CA   56.0  y      None      -56.0
3      CA   40.0  z      None      -40.0

Однако код возвращается

  country  value id new_col_1  new_col_2
0      US  100.0  a      None     -100.0
1      US   95.0  a      None      -95.0
2      US   56.0  a      None      -56.0
3      US   40.0  a      None      -40.0

Такое поведение наблюдается только в том случае, если в обеих группах одинаковое количество строк. Если в одной группе больше строк, результат будет таким, как ожидалось

Ответы [ 2 ]

2 голосов
/ 24 января 2020

Цитата из документации :

В текущей реализации примените вызовы fun c дважды к первому столбцу / строке, чтобы решить, может ли это быть быстрым или медленный путь кода. Это может привести к неожиданному поведению, если у потехи c есть побочные эффекты, поскольку они будут действовать дважды для первого столбца / строки.

Попробуйте изменить приведенный ниже код в своем коде:

def dummy_func(df_group):
    df_group['new_col_1'] = None

    # apply dummy_func_nested
    df_group = df_group.apply(dummy_func_nested, axis=1)

    return df_group

Кому:

def dummy_func(df_group):
    df_group['new_col_1'] = None

    # apply dummy_func_nested
    df_group = dummy_func_nested(df_group)

    return df_group

Вам не нужен apply.

Конечно, более эффективный способ будет:

df['new_col_1'] = None
df['new_col_2'] = -df['value']
print(df)

или:

print(df.assign(new_col_1=None, new_col_2=-df['value']))
0 голосов
/ 24 января 2020

При использовании groupby следует избегать использования методов apply () внутри функций, которые используют apply ()

Ниже приведен правильный код, который дает желаемые результаты.

Отказ от ответственности: код может быть написан более эффективно. Цель состоит в том, чтобы продемонстрировать, что мы должны избегать вызова apply() методов внутри groupby.apply(). Это отрицательно сказывается на том, что группы, к которым мы его применяем, имеют одинаковое количество строк в каждой группе. Если количество строк в каждой группе не равно, все идет гладко. Опять же, это происходит только тогда, когда группы имеют одинаковое количество строк.

Привет пользователю: u10-forward

import pandas as pd


def dummy_func_nested(df):
    df['new_col_2'] = df['value'] * -1
    return df


def dummy_func(df_group):
    df_group['new_col_1'] = None

    # apply dummy_func_nested
    df_group = dummy_func_nested(df_group)

    return df_group


def pandas_groupby():
    # initialize data
    df = pd.DataFrame([
        {'country': 'US', 'value': 100.00, 'id': 'a'},
        {'country': 'US', 'value': 95.00, 'id': 'b'},
        {'country': 'CA', 'value': 56.00, 'id': 'y'},
        {'country': 'CA', 'value': 40.00, 'id': 'z'},
    ])

    # group by country and apply first dummy_func
    new_df = df.groupby('country').apply(dummy_func)

    # new_df and df should have the same list of countries
    assert new_df['country'].tolist() == df['country'].tolist()
    print(df)


if __name__ == '__main__':
    pandas_groupby()

Тем не менее, я все еще думаю, что это ошибка, из-за невозможности вызова apply() методов внутри groupby.apply().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...