Este é o meu DataFrame:
import pandas as pd
df = pd.DataFrame(
{
'main': ['x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'y', 'y', 'y', 'y', 'y', 'y', 'y'],
'sub': ['c', 'c', 'c', 'd', 'd', 'e', 'e', 'e', 'e', 'f', 'f', 'f', 'f', 'g', 'g', 'g'],
'num_1': [10, 9, 80, 80, 99, 101, 110, 222, 90, 1, 7, 10, 2, 10, 95, 10],
'num_2': [99, 99, 99, 102, 102, 209, 209, 209, 209, 100, 100, 100, 100, 90, 90, 90]
}
)
E este é o meu resultado esperado. Quero adicionar coluna result
:
main sub num_1 num_2 result
0 x c 10 99 101
1 x c 9 99 101
2 x c 80 99 101
3 x d 80 102 110
4 x d 99 102 110
5 x e 101 209 222
6 x e 110 209 222
7 x e 222 209 222
8 x e 90 209 222
9 y f 1 100 NaN
10 y f 7 100 NaN
11 y f 10 100 NaN
12 y f 2 100 NaN
13 y g 10 90 95
14 y g 95 90 95
15 y g 10 90 95
A máscara é:
mask = (df.num_1 > df.num_2)
O processo começa assim:
a) A groupby
coluna ésub
b) Encontrar a primeira linha que atenda à condição da máscara para cada grupo.
c) Coloque o valor de num_1
noresult
Se não houver linhas que atendam à condição da máscara, a groupby
coluna será alterada para main
para encontrar a primeira linha de mask
. Há condição para esta fase:
O anterior subs
não deve ser considerado ao usar main
como groupby
coluna.
Um exemplo das etapas acima para agrupar d
na sub
coluna:
a) sub
é a groupby
coluna.
b) Não há linhas no d
grupo quedf.num_1 > df.num_2
Então agora para group d
, seu main
grupo é pesquisado. No entanto, o grupo c
também está neste main
grupo. Como é anterior a group d
, group c
não deve contar para esta etapa.
Nesta imagem mostrei de onde vêm esses valores:
E esta é a minha tentativa. Resolve parcialmente o problema para alguns grupos, mas não para todos:
def step_a(g):
mask = (g.num_1 > g.num_2)
g.loc[mask.cumsum().eq(1) & mask, 'result'] = g.num_1
g['result'] = g.result.ffill().bfill()
return g
a = df.groupby('sub').apply(step_a)
Código
definir função personalizada
fazer
result
colunadf:
IIUC, você pode usar a transmissão numpy para formar uma máscara por "principal" e usá-la para encontrar o primeiro num1> num2 considerando apenas os próximos grupos:
Observe que você pode facilmente ajustar as máscaras para executar outras lógicas (pesquisar nos próximos n grupos, excluir todos os grupos anteriores, exceto o anterior imediato, etc.).
Saídas:
Máscaras intermediárias
m
, aqui para o segundo exemplo: