Pandas groupby / apply имеет разное поведение с типами int и string - PullRequest
2 голосов
/ 10 июля 2019

У меня есть следующий фрейм данных

   X    Y
0  A   10
1  A    9
2  A    8
3  A    5
4  B  100
5  B   90
6  B   80
7  B   50

и две очень похожие функции

def func1(x):
    if x.iloc[0]['X'] == 'A':
        x['D'] = 1
    else:
        x['D'] = 0
    return x[['X', 'D']]

def func2(x):
    if x.iloc[0]['X'] == 'A':
        x['D'] = 'u'
    else:
        x['D'] = 'v'
    return x[['X', 'D']]

Теперь я могу группировать / применять эти функции

df.groupby('X').apply(func1)
df.groupby('X').apply(func2)

Первая строка дает мне то, что я хочу, то есть

   X  D
0  A  1
1  A  1
2  A  1
3  A  1
4  B  0
5  B  0
6  B  0
7  B  0

Но вторая строка возвращает что-то довольно странное

   X  D
0  A  u
1  A  u
2  A  u
3  A  u
4  A  u
5  A  u
6  A  u
7  A  u

Итак, мои вопросы:

  • Кто-нибудь может объяснить, почему поведение groupby / apply отличается при изменении типа?
  • Как получить что-то похожее с func2?

1 Ответ

0 голосов
/ 10 июля 2019

Проблема заключается в том, что функция, примененная к GroupBy, не должна никогда пытаться изменить получаемый кадр данных. Это зависит от реализации, является ли это копией (которую можно безопасно изменить, но изменения не будут видны в исходном кадре данных) или представлением. Выбор осуществляется оптимизатором pandas, и как пользователь вы должны просто знать, что он запрещен.

Правильный способ - заставить копию:

def func2(x):
    x = x.copy()
    if x.iloc[0]['X'] == 'A':
        x['D'] = 'u'
    else:
        x['D'] = 'v'
    return x[['X', 'D']]

После этого df.groupby('X').apply(func2).reset_index(level=0, drop=True) дает, как и ожидалось:

   X  D
0  A  u
1  A  u
2  A  u
3  A  u
4  B  v
5  B  v
6  B  v
7  B  v
...