Este é meu DataFrame:
import pandas as pd
df = pd.DataFrame({
'a': [10, 20, 30, 50, 50, 50, 4, 100],
'b': [30, 3, 200, 25, 24, 31, 29, 2],
'd': list('aaabbbcc')
})
Saída esperada:
a b d
0 10 30 a
1 20 3 a
2 30 200 a
O agrupamento é por coluna d
. Quero retornar os grupos que têm pelo menos duas instâncias desta máscara
m = (df.b.gt(df.a))
Foi isso que eu tentei. Funciona, mas me pergunto se há uma maneira melhor/mais eficiente de fazer isso.
out = df.groupby('d').filter(lambda x: len(x.loc[x.b.gt(x.a)]) >= 2)
Com pandas
Você pode usar a
groupby.transform
na máscara comsum
para produzir uma série booleana:Saída:
Intermediários:
Alternativa:
Com numpy
Alternativamente, pode-se evitar o custo
groupby
com o numpy puro.Esta primeira abordagem
add.reduceat
requer que os grupos sejam consecutivos:Este segundo com
pandas.factorize
enumpy.bincount
funcionaria mesmo com grupos embaralhados:Intermediários:
Horários
Com grupos de 3 linhas (membros classificados):
Com grupos de 3 linhas (membros embaralhados; NB. excluindo
reduceat
. ):Com um número fixo de 20 grupos (de tamanho aproximadamente igual) com membros consecutivos:
Com um número fixo de 20 grupos (de tamanho aproximadamente igual) com membros embaralhados ( NB. excluindo
reduceat
. ):