Eu tenho o seguinte código:
import pandas as pd
series_source = pd.Series([1, 2, 3, 4], dtype=int)
normal_index = pd.Series([True, False, True, True], dtype=bool)
big_index = pd.Series([True, False, True, True, False, True], dtype=bool)
# Both indexes give back: pd.Series([1, 2, 3, 4], dtype=int)
# no warnings are raised!
assert (series_source[normal_index] == series_source[big_index]).all()
df_source = pd.DataFrame(
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]
]
)
# no warning - works as expected: grabs rows 0, 2, and 3
df_normal_result = df_source[normal_index]
# UserWarning: Boolean Series key will be reindexed to match DataFrame index.
# (but still runs)
df_big_result = df_source[big_index]
# passes - they are equivalent
assert df_normal_result.equals(df_big_result)
print("Complete")
Por que indexar the series_source
com the big_index
não gera um aviso, mesmo que o índice grande tenha mais valores que a fonte? O que os pandas estão fazendo nos bastidores para fazer a indexação da série?
(Compare isso com a indexação do df_source
, onde é gerado um aviso explícito que big_index
precisa ser reindexado para que a operação funcione.)
Nos documentos de indexação , afirma que:
Usar um vetor booleano para indexar uma série funciona exatamente como em um ndarray NumPy
No entanto, se eu fizer
import numpy as np
a = np.array([1, 2, 3, 4, 5])
b = np.array([True, False, True, True, False])
c = np.array([True, False, True, True, False, True, True])
# returns an ndarray of [1,3, 4] as expected
print(a[b])
# raises IndexError: boolean index did not match indexed array along axis 0;
# size of axis is 5 but size of corresponding boolean axis is 7
print(a[c])
Portanto, não parece que essa funcionalidade corresponda ao Numpy, como afirmam os documentos. O que está acontecendo?
(Minhas versões são pandas==2.2.2
e numpy==2.0.0
.)
Porque a série de indexação é primeiro alinhada ao índice do DataFrame/Série indexado.
Resumindo, o pandas está fazendo:
Exemplo para uma série:
Na verdade, você mesmo pode observar isso se alterar os índices da série de indexação:
Saída:
Temos 4 linhas na saída, apesar dos dois primeiros valores serem
False
. Após a reindexação, os valores booleanos são[True, True, True, True]
.Você deve receber um aviso neste caso:
Observe que se o alinhamento não puder ser feito, um erro será gerado, como em numpy:
por que isso acontece com DataFrame[Series] mas não com Series[Series]?
Porque há uma verificação para DataFrame[Series]
Esclarecendo meu aprendizado com a resposta de @mozway :
Ao indexar a
pd.Series
oupd.DataFrame
com apd.Series[bool]
, o pandas combinará os rótulos dos valores na série de origem (ou os rótulos das linhas no dataframe de origem) com os rótulos encontrados na série de indexação. Este processo é feito internamente através doreindex
método:bool_series.reindex(source.index)
.Observe que se um rótulo estiver na fonte e não estiver no indexador booleano, a reindexação não será possível e, portanto, o programa gerará um erro.
Se a fonte for um dataframe e os rótulos da série booleana de indexação não corresponderem exatamente aos rótulos do dataframe de origem (
source_df.index != bool_series.index
), o programa emitirá um aviso indicando que a reindexação será feita. No entanto, se a fonte for uma série e os rótulos não corresponderem exatamente a (source_series.index != bool_series.index
), nenhum aviso será gerado (apenas reindexará silenciosamente a série booleana). Este é apenas um detalhe de implementação.