Este é o meu dataframe:
df = pd.DataFrame(
{
'a': [0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0],
'b': [1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1]
}
)
E esta é a saída que eu quero. Quero criar uma coluna c
:
a b c
0 0 1 0
1 0 -1 0
2 1 -1 0
3 1 -1 0
4 1 1 1
5 1 -1 1
6 0 1 0
7 0 1 0
8 0 -1 0
9 1 1 1
10 1 1 1
11 1 -1 1
12 0 1 0
13 0 1 0
14 1 -1 0
15 1 -1 1
16 0 1 0
Esta é basicamente uma extensão deste post . As linhas destacadas abaixo resumem a maneira como isso precisa ser feito.
Primeiro de tudo, na coluna a
, os grupos são criados por sequência de 1s e uma linha após o término da sequência. As linhas destacadas na coluna a
são esses grupos. A solução para esta etapa está aqui .
Agora o que preciso é verificar a coluna b
de cada grupo no arquivo a
. Encontre o primeiro valor que é 1 pol b
para cada grupo. E então qualquer valor que vier antes disso se tornará 0. É assim que a coluna c
é criada.
Por exemplo, para o primeiro grupo em a
, o primeiro valor da coluna b
é 1 é o número da linha 4
. Os valores anteriores nesse grupo tornam-se 0. E o resultado é o primeiro grupo destacado na coluna c
.
Observe que se para um grupo todos os valores b
NÃO forem 1, o grupo correspondente se c
tornará todos 0s.
Isto é o que eu tentei, mas não consigo encontrar a solução completa:
g = df.loc[::-1, 'a'].eq(0).cumsum()
x = df.groupby(g).filter(lambda x: x.b.iloc[0] == 1)
Uma variação da resposta vinculada usando
groupby.cummax
ondf['b'].eq(1)
e uma máscara intermediária derivada da garoupa:Saída e intermediários:
Crie uma máscara por
GroupBy.cummax
e encadeie comSeries.duplicated
, para definir0,1
a conversão de booleano para números inteiros: