ti-enxame.com

Pandas O método GroupBy.apply duplica o primeiro grupo

Minha primeira pergunta SO: Estou confusa sobre esse comportamento do método apply de groupby em pandas (0.12.0-4), parece aplicar a função DUAS VEZES para a primeira linha de um quadro de dados.Por exemplo:

>>> from pandas import Series, DataFrame
>>> import pandas as pd
>>> df = pd.DataFrame({'class': ['A', 'B', 'C'], 'count':[1,0,2]})
>>> print(df)
   class  count  
0     A      1  
1     B      0    
2     C      2

Primeiro, verifico se a função groupby funciona bem e parece estar bem:

>>> for group in df.groupby('class', group_keys = True):
>>>     print(group)
('A',   class  count
0     A      1)
('B',   class  count
1     B      0)
('C',   class  count
2     C      2)

Em seguida, tento fazer algo semelhante usando apply no objeto groupby e recebo a saída da primeira linha duas vezes:

>>> def checkit(group):
>>>     print(group)
>>> df.groupby('class', group_keys = True).apply(checkit)
  class  count
0     A      1
  class  count
0     A      1
  class  count
1     B      0
  class  count
2     C      2

Qualquer ajuda seria apreciada! Obrigado.

Edit: @Jeff fornece a resposta abaixo. Sou denso e não o entendi imediatamente, portanto, aqui está um exemplo simples para mostrar que, apesar da impressão dupla do primeiro grupo no exemplo acima, o método apply opera apenas uma vez no primeiro grupo e não altera o quadro de dados original :

>>> def addone(group):
>>>     group['count'] += 1
>>>     return group

>>> df.groupby('class', group_keys = True).apply(addone)
>>> print(df)

      class  count
0     A      1
1     B      0
2     C      2

Mas, atribuindo o retorno do método a um novo objeto, vemos que ele funciona como esperado:

df2 = df.groupby ('classe', group_keys = True) .apply (addone) print (df2)

      class  count
0     A      2
1     B      1
2     C      3
38
NC maize breeding Jim

Isso ocorre por design, conforme descrito aqui e aqui

A função apply precisa conhecer a forma dos dados retornados para descobrir de maneira inteligente como eles serão combinados. Para fazer isso, ele chama a função (checkit no seu caso) duas vezes para conseguir isso.

Dependendo do seu caso de uso real, você pode substituir a chamada para apply por aggregate, transform ou filter, conforme descrito em detalhes aqui . Essas funções exigem que o valor de retorno tenha uma forma específica e, portanto, não chame a função duas vezes.

No entanto - se a função que você está chamando não tiver efeitos colaterais, provavelmente não importa que a função esteja sendo chamada duas vezes no primeiro valor.

37
Zero

Este "problema" foi corrigido: atualize para 0.25+

A partir da v0.25, GroupBy.apply() avaliará o primeiro grupo apenas uma vez. Veja GH24748 .

Exemplo relevante da documentação:

pd.__version__                                                                                                          
# '0.25.0.dev0+590.g44d5498d8'

df = pd.DataFrame({"a": ["x", "y"], "b": [1, 2]})                                                                      

def func(group): 
    print(group.name) 
    return group                                                                                                                     

Novo comportamento (> = v0.25):

df.groupby('a').apply(func)                                                                                            
x
y

   a  b
0  x  1
1  y  2

Comportamento antigo (<= v0.24.x):

df.groupby('a').apply(func)
x
x
y

   a  b
0  x  1
1  y  2

O Pandas ainda usa o primeiro grupo para determinar se apply pode seguir um caminho rápido ou não. Mas pelo menos não precisa mais avaliar o primeiro grupo duas vezes. Bom trabalho, devs!

9
cs95

você pode usar o loop for para evitar a primeira linha groupby.apply duplicada,

log_sample.csv

guestid,keyword
1,null
2,null
2,null
3,null
3,null
3,null
4,null
4,null
4,null
4,null

meu snippit de código

df=pd.read_csv("log_sample.csv") 
grouped = df.groupby("guestid")

for guestid, df_group in grouped:
    print(list(df_group['guestid'])) 

df.head(100)

resultado

[1]
[2, 2]
[3, 3, 3]
[4, 4, 4, 4]
2
geosmart