Uma daquelas coisas irritantes que todos estamos tentando descobrir quando aprendemos o Pandas é a distinção entre .loc
e .iloc
.
Vamos acabar com essa confusão e esclarecer a diferença entre esses dois métodos. Vou fornecer muitos exemplos, e espero que a distinção fique muito mais clara até o final deste blog.
O que são .loc e .iloc no Pandas?
Tanto .loc
quanto .iloc
são atributos essenciais dos DataFrames do Pandas, e ambos são usados para selecionar subconjuntos específicos de dados. Seu objetivo é acessar e permitir a manipulação de uma parte específica do DataFrame em vez de todo o DataFrame.
Recurso |
.loc |
.iloc |
Sintaxe |
df.loc[row_indexer, column_indexer] |
df.iloc[row_indexer, column_indexer] |
Método de indexação |
Indexação baseada em rótulos |
Indexação baseada em posições |
Usado para Referência |
Rótulos de linhas e colunas |
Índices numéricos de linhas e colunas (começando do 0) |
Como podemos ver na tabela, a sintaxe se parece muito similar. A diferença está em como usamos os argumentos row_indexer
e column_indexer
. Isso acontece porque os dois métodos oferecem abordagens diferentes para indexar os dados: enquanto o .loc
indexa com base nos nomes dos rótulos, o .iloc
utiliza o índice numérico da posição das linhas e colunas como argumentos.
Vamos examinar cada um dos dois métodos em detalhes, começando pelo .loc
.
Usando .loc: Seleção por Rótulos
Para ilustrar os conceitos, vamos considerar um banco de dados de clientes hipotético representado por este DataFrame chamado df
, com o ID do Cliente
representando o índice da linha:
ID do Cliente |
Nome |
País |
Região |
Idade |
C123 |
John Doe |
Estados Unidos |
América do Norte |
67 |
C234 |
Petra Müller |
Alemanha |
Europa |
51 |
C345 |
Ali Khan |
Pakistan |
Ásia |
19 |
C456 |
Maria Gonzalez |
México |
América do Norte |
26 |
C567 |
David Lee |
China |
Ásia |
40 |
Existem quatro maneiras principais de selecionar linhas com .loc
. Estas incluem:
- Selecionar uma única linha
- Selecionando várias linhas
- Selecionando um intervalo de linhas
- Seleção condicional de linhas
Selecionando uma única linha usando .loc
Para selecionar uma única linha, usamos o rótulo da linha que queremos recuperar como row_indexer
. Dessa forma, a sintaxe fica assim: df.loc['row_label']
. Vamos usar isso para exibir todas as informações do nosso cliente Ali Khan:
df.loc['C345']
C345 |
|
Nome |
Ali Khan |
País |
Pakistan |
Região |
Ásia |
Idade |
19 |
Selecionando várias linhas usando .loc
Se quisermos selecionar várias linhas que não seguem necessariamente uma após a outra, precisamos passar uma lista com os rótulos de linha como argumento row_indexer
. Isso significa que precisamos usar não um, mas dois pares de colchetes: um para a sintaxe regular do .loc
e outro para a lista de rótulos.
A linha df.loc[['rótulo_linha_1', 'rótulo_linha_2']]
irá retornar as duas linhas do DataFrame df
especificadas na lista. Digamos que quiséssemos saber não apenas as informações sobre Ali Khan, mas também sobre David Lee:
df.loc[['C345', 'C567']]
ID do Cliente |
Nome |
País |
Região |
Idade |
C345 |
Ali Khan |
Pakistan |
Ásia |
19 |
C567 |
David Lee |
China |
Ásia |
40 |
Selecionando um conjunto de linhas usando .loc
Podemos selecionar uma faixa de linhas passando os rótulos da primeira e última linha com dois pontos no meio: df.loc['rótulo_linha_inicial':'rótulo_linha_final']
. Poderíamos exibir as primeiras quatro linhas do nosso DataFrame assim:
df.loc['C123' : 'C456']
Identificação do Cliente |
Nome |
País |
Região |
Data de Inscrição |
C123 |
John Doe |
Estados Unidos |
América do Norte |
67 |
C234 |
Petra Müller |
Alemanha |
Europa |
51 |
C345 |
Ali Khan |
Pakistan |
Ásia |
19 |
C456 |
Maria Gonzalez |
México |
América do Norte |
26 |
Aqui, há duas coisas a ter em mente:
- A saída inclui a linha especificada em
row_label_end
. Isso é diferente em.iloc
, que abordaremos mais tarde. - Usamos apenas um par de colchetes, mesmo que queiramos recuperar várias linhas. Não usamos uma lista para especificar as várias linhas, então usar dois colchetes retornaria um
SyntaxError
.
Seleção condicional de linhas usando .loc
Também podemos retornar linhas com base em uma expressão condicional. Podemos filtrar todas as linhas com base em se elas atendem ou não a uma certa condição e exibir apenas aquelas que atendem.
A sintaxe correspondente é df.loc[conditional_expression]
, com a conditional_expression
sendo uma declaração sobre os valores permitidos em uma coluna específica.
Para colunas com dados não numéricos (como Nome
ou País
), a declaração só pode usar o operador de igual ou diferente, pois não há ordem entre os valores. Poderíamos, por exemplo, retornar todas as linhas de clientes que não são da Ásia:
df.loc[df['Region'] != 'Asia']
ID do Cliente |
Nome |
País |
Região |
Idade |
C123 |
John Doe |
Estados Unidos |
América do Norte |
67 |
C234 |
Petra Müller |
Alemanha |
Europa |
51 |
C456 |
Maria Gonzalez |
México |
América do Norte |
26 |
Selecionando uma única coluna usando .loc
Para selecionar colunas, precisamos especificar o argumento column_indexer
, que vem após o argumento row_indexer
. Se queremos especificar apenas o column_indexer
, precisamos de alguma forma indicar que queremos retornar todas as linhas e filtrar apenas as colunas. Vamos ver como podemos fazer isso!
Selecionar uma única coluna pode ser feito especificando o column_indexer
com o rótulo da respectiva coluna. Para recuperar todas as linhas, precisamos especificar o row_indexer
com dois pontos simples. Chegamos a uma sintaxe que se parece com isso: df.loc[:, 'nome_da_coluna']
.
Vamos exibir o Nome
de cada cliente:
df.loc[:, 'Name']
ID do Cliente |
Nome |
C123 |
João Ninguém |
C234 |
Petra Müller |
C345 |
Ali Khan |
C456 |
Maria Gonzalez |
C567 |
David Lee |
Selecionar várias colunas usando .loc
Igual à seleção de várias linhas, precisamos passar uma lista de rótulos de coluna se quisermos retornar várias colunas de um DataFrame que não necessariamente seguem uma após a outra em ordem: df.loc[:, [col_label_1, 'col_label_2']]
.
Supondo que quiséssemos adicionar todas as idades dos clientes ao nosso último resultado, funcionaria assim:
df.loc[:, ['Name', 'Age']]
ID do Cliente |
Nome |
Idade |
C123 |
John Doe |
67 |
C234 |
Petra Müller |
51 |
C345 |
Ali Khan |
19 |
C456 |
Maria Gonzalez |
26 |
C567 |
David Lee |
40 |
Selecionando uma fatia de colunas usando .loc
Usar dois pontos entre os rótulos de duas colunas selecionará todas as colunas no intervalo entre as duas colunas especificadas. É inclusivo da coluna final, o que significa que a coluna chamada col_end
também será selecionada na sintaxe padrão, que é a seguinte: df.loc[:, 'col_start':'col_end']
.
Se estivéssemos interessados no Nome
, País
e Região
de nossos clientes, nossa linha de código poderia ser:
df.loc[:, 'Name':'Region']
ID do Cliente |
Nome |
País |
Região |
C123 |
John Doe |
Estados Unidos |
América do Norte |
C234 |
Petra Müller |
Alemanha |
Europa |
C345 |
Ali Khan |
Pakistan |
Ásia |
C456 |
Maria Gonzalez |
México |
América do Norte |
C567 |
David Lee |
China |
Ásia |
Seleção combinada de linhas e colunas usando .loc
Também é possível especificar tanto o row_indexer
quanto o column_indexer
. Isso pode ser usado para recuperar uma única informação, ou seja, uma célula do DataFrame. Para fazer isso, especificamos uma linha e uma coluna usando a sintaxe df.loc['row_label', 'column_name']
.
O caso mais útil é retornar um sub-DataFrame que se concentre exatamente no conjunto de linhas e colunas que nos interessa. É possível especificar ambos os indexadores como listas usando colchetes, ou como um intervalo usando dois pontos, e até mesmo combiná-lo com uma expressão condicional para a seleção de linhas.
Aqui está um exemplo de retorno do Name
, Country
e Region
de cada cliente com uma Age
acima de 30:
df.loc[df['Age'] > 30, 'Name':'Region']
ID do Cliente |
Nome |
País |
Região |
C123 |
John Doe |
Estados Unidos |
América do Norte |
C234 |
Petra Müller |
Germany |
Europe |
C567 |
David Lee |
China |
Asia |
Usando .iloc: Seleção por Posição Inteira
.iloc
seleciona pela posição em vez do rótulo. Esta é a sintaxe padrão de uso do .iloc
: df.iloc[indice_da_linha, indice_da_coluna]
. Há duas coisas especiais para se observar:
- Contagem a partir de 0: A primeira linha e coluna têm o índice 0, a segunda tem índice 1, etc.
- Exclusividade do valor final do intervalo: Ao usar um intervalo, a linha ou coluna especificada após os dois pontos não está incluída na seleção.
Selecionando uma única linha usando .iloc
Uma única linha pode ser selecionada usando o inteiro que representa o número do índice da linha como o indice_da_linha
. Não precisamos de aspas, pois estamos inserindo um número inteiro e não uma string de rótulo como fizemos com .loc
. Para retornar a primeira linha de um DataFrame chamado df
, insira df.iloc[0]
.
Em nosso exemplo de DataFrame, esta mesma linha de código retorna as informações de John Doe:
df.iloc[0]
C123 |
|
Nome |
John Doe |
País |
Estados Unidos |
Região |
América do Norte |
Idade |
67 |
Selecionando várias linhas usando .iloc
Selecionar várias linhas funciona no .iloc
assim como no .loc
—digitamos os índices das linhas em uma lista com colchetes. A sintaxe parece com isso: df.iloc[[0, 3, 4]]
.
A saída respectiva em nossa tabela de clientes pode ser vista abaixo:
df.iloc[[0, 3, 4]]
ID do Cliente |
Nome |
País |
Região |
Idade |
C123 |
John Doe |
Estados Unidos |
América do Norte |
67 |
C456 |
Maria Gonzalez |
México |
América do Norte |
26 |
C567 |
David Lee |
China |
Ásia |
40 |
Selecionando uma fatia de linhas usando .iloc
Para selecionar uma fatia de linhas, usamos dois inteiros de índice de linha especificados separados por dois pontos. Agora, devemos prestar atenção à exclusividade mencionada anteriormente.
Podemos pegar a linha df.iloc[1:4]
como exemplo para ilustrar esse conceito. O número de índice 1 significa a segunda linha, então nossa fatia começa lá. O inteiro de índice 4 representa a quinta linha – mas como o .iloc
não é inclusivo para seleção de fatia, nossa saída incluirá todas as linhas até a última antes desta. Portanto, retornará a segunda, terceira e quarta linhas.
Vamos provar que a linha funciona como deveria:
df.iloc[1:4]
ID do Cliente |
Nome |
País |
Região |
Idade |
C234 |
Petra Müller |
Alemanha |
Europa |
51 |
C345 |
Ali Khan |
Paquistão |
Ásia |
19 |
C456 |
Maria Gonzalez |
México |
América do Norte |
26 |
Selecionando uma única coluna usando .iloc
A lógica de seleção de colunas usando .iloc
segue o que aprendemos até agora. Vamos ver como funciona para colunas únicas, múltiplas colunas e fatias de colunas.
Assim como com .loc
, é importante especificar o row_indexer
antes de prosseguir para o column_indexer
. Para recuperar os valores da terceira coluna do df
para cada linha, digitamos df.iloc[:, 2]
.
Como Region
é a terceira coluna em nosso DataFrame, ela será recuperada como consequência dessa linha de código:
df.iloc[:, 2]
ID do Cliente |
Região |
C123 |
América do Norte |
C234 |
Europa |
C345 |
Ásia |
C456 |
América do Norte |
C567 |
Ásia |
Selecionando múltiplas colunas usando .iloc
Para selecionar múltiplas colunas que não são necessariamente subsequentes, podemos novamente inserir uma lista contendo inteiros como o column_indexer
. A linha df.iloc[:, [0, 3]]
retorna tanto a primeira quanto a quarta coluna.
No nosso caso, as informações exibidas são o Nome
assim como a Idade
de cada cliente:
df.iloc[:, [0, 3]]
ID do Cliente |
Nome |
Idade |
C123 |
John Doe |
67 |
C234 |
Petra Müller |
51 |
C345 |
Ali Khan |
19 |
C456 |
Maria Gonzalez |
26 |
C567 |
David Lee |
40 |
Selecionando um intervalo de colunas usando .iloc
Para seleção de fatiamento usando .iloc
, a lógica do column_indexer
segue a do row_indexer
. A coluna representada pelo número inteiro após os dois pontos não está incluída na saída. Para recuperar a segunda e a terceira colunas, a linha de código deve ser assim: df.iloc[:, 1:3]
.
Esta linha abaixo retorna todas as informações geográficas que temos sobre nossos clientes:
df.iloc[:, 1:3]
ID do Cliente |
País |
Região |
C123 |
Estados Unidos |
América do Norte |
C234 |
Alemanha |
Europa |
C345 |
Paquistão |
Ásia |
C456 |
México |
América do Norte |
C567 |
China |
Ásia |
Seleção combinada de linha e coluna usando .iloc
Podemos juntar o que aprendemos sobre .iloc
para combinar a seleção de linha e coluna. Novamente, é possível retornar uma única célula ou um sub-DataFrame. Para retornar a única célula na interseção da linha 3 e coluna 4, inserimos df.iloc[2, 3]
.
Assim como com .loc
, podemos especificar ambos os indexadores como listas usando os colchetes, ou como um intervalo usando dois pontos. Se quisermos selecionar linhas usando expressões condicionais, isso é tecnicamente possível com .iloc
também, mas não é recomendado. Usar os nomes de rótulo e .loc
geralmente é muito mais intuitivo e menos propenso a erros.
Este último exemplo exibe País
, Região
e Idade
para a primeira, segunda e quinta linha em nosso DataFrame:
df.iloc[[0,1,4], 1:4]
ID do Cliente |
País |
Região |
Idade |
C123 |
Estados Unidos |
América do Norte |
67 |
C234 |
Alemanha |
Europa |
51 |
C567 |
China |
Ásia |
40 |
.iloc vs .loc: Quando Usar Qual
Geralmente, há uma regra simples para decidir qual método usar com base no seu conhecimento do DataFrame:
- Use
.loc
quando você conhece os rótulos (nomes) das linhas/colunas. - Use
.iloc
quando você conhece as posições inteiras das linhas/colunas.
Alguns cenários favorecem o uso de .loc
ou .iloc
por sua natureza. Por exemplo, iterar sobre linhas ou colunas é mais fácil e intuitivo usando números inteiros do que rótulos. Como já mencionamos, filtrar linhas com base em condições nos valores das colunas é menos propenso a erros usando os nomes dos rótulos das colunas.
Cenários Favoráveis ao .loc |
Cenários Favoráveis ao .iloc |
Seu DataFrame tem nomes significativos de índice/coluna. |
Você está iterando sobre linhas/colunas pela posição delas. |
Você precisa filtrar com base em condições nos valores das colunas. |
Os nomes de índice/coluna não são relevantes para a sua tarefa. |
KeyError, NameError e Index Error com .loc e .iloc
Vamos dar uma olhada nos possíveis problemas. Uma armadilha comum ao usar .loc
é encontrar um KeyError
. Esse erro ocorre quando tentamos acessar um rótulo de linha ou coluna que não existe em nosso DataFrame. Para evitar isso, sempre devemos garantir que os rótulos que estamos usando sejam precisos e correspondam aos rótulos existentes em seu DataFrame e verificar novamente quanto a erros de digitação.
Além disso, é importante sempre usar aspas para os rótulos especificados usando .loc
. Esquecer delas retornará um NameError
.
Um IndexError
pode ocorrer ao usar .iloc
se especificarmos uma posição inteira que está fora do intervalo válido dos índices do nosso DataFrame. Isso acontece quando o índice que você está tentando acessar não existe, seja porque está além do número de linhas ou colunas em seu DataFrame ou porque é um valor negativo. Para evitar esse erro, verifique as dimensões do seu DataFrame e use valores de índice apropriados dentro do intervalo válido.
Conclusão
Espero que este blog tenha sido útil e que a distinção entre .loc
e .iloc
esteja clara agora. Para aprender mais, aqui estão alguns bons próximos passos: