9 min de leitura
#4 - Selecionando e Filtrando Dados com loc, iloc e Máscaras Booleanas
Como selecionar linhas e colunas específicas de um DataFrame com .loc e .iloc, e como filtrar dados com máscaras booleanas e o método .query().
Nos três primeiros posts desta série você aprendeu a criar, carregar, limpar, correlacionar e visualizar dados com o Pandas — o suficiente pra sair fazendo análises de verdade. A partir de agora a série volta ao Pandas pra aprofundar em técnicas que você vai usar o tempo todo: selecionar exatamente as linhas e colunas que interessam, filtrar dados por condição, agrupar e agregar, combinar tabelas diferentes, tratar texto e trabalhar com datas.
Neste post o assunto é seleção e filtragem: como pedir pro Pandas “me dê só essa parte da tabela”.
Revisão rápida: colchetes simples
Antes de entrar em .loc e .iloc, vale relembrar o jeito mais básico de selecionar colunas, já usado nos posts anteriores — colchetes direto no DataFrame:
import pandas as pd
dados = {
"produto": ["Notebook", "Mouse", "Teclado", "Monitor", "Headset"],
"categoria": ["Informática", "Informática", "Informática", "Informática", "Áudio"],
"preco": [3200, 89, 150, 890, 220],
"estoque": [12, 45, 30, 8, 20]
}
df = pd.DataFrame(dados)
print(df["produto"])
print(df[["produto", "preco"]])
Um colchete com um nome só devolve uma Series (a coluna); colchete duplo com uma lista de nomes devolve um DataFrame com aquelas colunas. Isso funciona bem pra colunas, mas não é o jeito recomendado de selecionar linhas — é aí que entram .loc e .iloc.
Selecionando com .loc (por rótulo)
O .loc já apareceu de leve no primeiro post da série, pra buscar uma linha pelo índice. Na prática ele aceita uma sintaxe bem mais rica: df.loc[linhas, colunas], onde tanto linhas quanto colunas podem ser um rótulo único, uma lista de rótulos, um slice ou uma máscara booleana.
Exemplo 1 - linhas e colunas específicas
print(df.loc[[0, 2, 4], ["produto", "preco"]])
A saída é:
produto preco
0 Notebook 3200
2 Teclado 150
4 Headset 220
Exemplo 2 - slice de linhas com .loc
print(df.loc[1:3, "produto":"preco"])
produto categoria preco
1 Mouse Informática 89
2 Teclado Informática 150
3 Monitor Informática 890
Nota: slices com
.locincluem o rótulo final —1:3traz as linhas1,2e3, diferente do fatiamento comum de listas Python, onde o limite superior fica de fora. O mesmo vale pro slice de colunas:"produto":"preco"inclui a própria colunapreco.
Exemplo 3 - todas as linhas, uma coluna
print(df.loc[:, "categoria"])
O : sozinho significa “todas as linhas”, exatamente como no fatiamento de listas.
Selecionando com .iloc (por posição)
Enquanto .loc busca por rótulo, .iloc busca pela posição numérica — começando em 0, igual a listas e arrays do NumPy. É a escolha certa quando você quer “a terceira linha” ou “as duas últimas colunas”, independente de como os índices foram rotulados.
Exemplo 4 - linhas e colunas por posição
print(df.iloc[0:2, 0:2])
produto categoria
0 Notebook Informática
1 Mouse Informática
Diferente do .loc, o slice 0:2 aqui não inclui a posição 2 — segue a mesma regra de qualquer fatiamento Python.
Exemplo 5 - a última linha, com índice negativo
print(df.iloc[-1])
produto Headset
categoria Áudio
preco 220
estoque 20
Name: 4, dtype: object
Índices negativos funcionam com .iloc do mesmo jeito que numa lista Python — -1 é sempre a última posição, mesmo que os rótulos do índice sejam outra coisa.
Nota: um jeito fácil de lembrar a diferença:
.loc= location por rótulo (label),.iloc= integer location por posição. Se os rótulos do seu índice já forem números sequenciais a partir de0, os dois podem até devolver o mesmo resultado num slice simples — mas o comportamento diverge assim que o índice é reordenado, filtrado ou nomeado com texto.
Filtrando com máscaras booleanas
Selecionar por posição ou rótulo é útil, mas o mais comum no dia a dia é filtrar por condição — “só os produtos com preço acima de 200”, por exemplo. O Pandas faz isso com máscaras booleanas: uma Series de True/False, uma posição pra cada linha, que serve de filtro dentro dos colchetes.
Exemplo 6 - uma condição simples
caros = df["preco"] > 200
print(caros)
0 True
1 False
2 False
3 True
4 True
Name: preco, dtype: bool
print(df[caros])
produto categoria preco estoque
0 Notebook Informática 3200 12
3 Monitor Informática 890 8
4 Headset Áudio 220 20
Na prática, quase sempre a máscara é escrita direto dentro dos colchetes, sem passar por uma variável intermediária:
print(df[df["preco"] > 200])
Exemplo 7 - combinando condições
Pra combinar mais de uma condição, use & (e) ou | (ou) — não os operadores and/or do Python puro, que não funcionam elemento a elemento numa Series. Cada condição precisa ficar entre parênteses:
filtro = (df["categoria"] == "Informática") & (df["preco"] < 200)
print(df[filtro])
produto categoria preco estoque
1 Mouse Informática 89 30
2 Teclado Informática 150 30
E pra negar uma condição inteira, o ~ faz o papel do not:
print(df[~(df["categoria"] == "Áudio")])
Isso devolve todas as linhas cuja categoria não é “Áudio”.
Exemplo 8 - filtrando e escolhendo colunas ao mesmo tempo
.loc aceita uma máscara booleana no lugar das linhas, o que permite filtrar e escolher colunas numa única chamada:
print(df.loc[df["preco"] > 200, ["produto", "preco"]])
produto preco
0 Notebook 3200
3 Monitor 890
4 Headset 220
Filtrando com query()
Pra condições mais longas, encadear várias máscaras entre parênteses pode ficar difícil de ler. O método .query() aceita a condição como uma string, com uma sintaxe mais parecida com SQL:
Exemplo 9 - a mesma condição, com query()
print(df.query("categoria == 'Informática' and preco < 200"))
produto categoria preco estoque
1 Mouse Informática 89 30
2 Teclado Informática 150 30
Repare que dentro da string do .query() os operadores voltam a ser and, or e not normais — é só fora dele, nas máscaras booleanas comuns, que valem &, | e ~.
Exemplo 10 - usando uma variável Python dentro do query()
Pra referenciar uma variável externa dentro da string, prefixe o nome com @:
preco_minimo = 200
print(df.query("preco > @preco_minimo"))
Com .loc, .iloc, máscaras booleanas e .query() no repertório, você já consegue recortar qualquer DataFrame exatamente do jeito que precisa. No próximo post, o passo natural depois de filtrar dados é resumi-los: vamos ver como agrupar linhas por categoria e calcular agregações com groupby().
Fonte adaptada: Pandas - Indexing and Selecting Data, Pandas - Boolean Indexing, Pandas - Boolean Masking
Comentários