Uma daquelas coisas irritantes que todos nós estamos tentando entender quando aprendemos 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 dar 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?
Ambos .loc
e .iloc
são atributos essenciais dos DataFrames do Pandas, e ambos são usados para selecionar subconjuntos específicos de dados. Seu propósito é acessar e permitir a manipulação de uma parte específica do DataFrame em vez do DataFrame inteiro.
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ção |
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 parece muito semelhante. A diferença está em como usamos os argumentos row_indexer
e column_indexer
. Isso ocorre 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 de posição numérica 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 Etiquetas
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 |
João Silva |
Estados Unidos |
América do Norte |
67 |
C234 |
Petra Müller |
Alemanha |
Europa |
51 |
C345 |
Ali Khan |
Paquistão |
Á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:
- Selecionando 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
. De acordo com isso, a sintaxe se parece com isto: df.loc['row_label']
. Vamos usar isso para exibir todas as informações sobre nosso cliente Ali Khan:
df.loc['C345']
C345 |
|
Nome |
Ali Khan |
País |
Paquistão |
Região |
Ásia |
Idade |
19 |
Selecionando várias linhas usando .loc
Se quisermos selecionar várias linhas que não necessariamente seguem uma à outra em ordem, precisamos passar uma lista de seus rótulos de linha como argumento row_indexer
. Isso significa que precisamos usar não uma, mas duas pares de colchetes: um para a sintaxe regular .loc
e outro para a lista de rótulos.
A linha df.loc[['row_label_1', 'row_label_2']]
retornará as duas linhas do DataFrame df
especificadas na lista. Vamos supor 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 |
Paquistão |
Ásia |
19 |
C567 |
David Lee |
China |
Ásia |
40 |
Selecionando uma fatia de linhas usando .loc
Podemos selecionar um intervalo de linhas passando os rótulos da primeira e da última linha com dois pontos entre eles: df.loc['row_label_start':'row_label_end']
. Poderíamos exibir as quatro primeiras linhas do nosso DataFrame assim:
df.loc['C123' : 'C456']
ID 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 |
Paquistão |
Ásia |
19 |
C456 |
Maria Gonzalez |
México |
América do Norte |
26 |
Aqui estão 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]
, sendo conditional_expression
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 igualdade ou desigualdade, 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 |
João da Silva |
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 quisermos apenas especificar o column_indexer
, precisamos de alguma forma indicar que queremos retornar todas as linhas e filtrar apenas nas 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 isto: df.loc[:, 'column_name']
.
Vamos exibir o Nome
de cada cliente:
df.loc[:, 'Name']
ID do Cliente |
Nome |
C123 |
John Doe |
C234 |
Petra Müller |
C345 |
Ali Khan |
C456 |
Maria Gonzalez |
C567 |
David Lee |
Selecionando várias colunas usando .loc
Semelhante à 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 a Idade
de todos os clientes à nossa última saída, 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 na faixa de ordem entre as duas colunas especificadas. Isso inclui a 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 estivermos 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 |
Paquistão |
Ásia |
C456 |
Maria Gonzalez |
México |
América do Norte |
C567 |
David Lee |
China |
Ásia |
Seleção combinada de linha e coluna usando .loc
Também é possível especificar tanto o row_indexer
quanto o column_indexer
. Isso pode ser usado para recuperar uma única peça de 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 concentra exatamente no conjunto de linhas e colunas de nosso interesse. É possível especificar ambos os indexadores como listas usando os colchetes, ou como uma fatia usando dois pontos, e até combiná-lo com uma expressão condicional para a seleção de linha.
Aqui está um exemplo de retorno do Name
, Country
e Region
de cada cliente com um Age
superior a 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 por posição em vez de rótulo. Esta é a sintaxe padrão para usar .iloc
: df.iloc[indice_linha, indice_coluna]
. Existem duas coisas especiais para observar:
- Contagem iniciando em 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 número inteiro que representa o índice da linha como o indice_linha
. Não precisamos de aspas, já que 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 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 em .iloc
como em .loc
—nós inserimos os índices das linhas em uma lista com colchetes. A sintaxe é assim: 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 um segmento de linhas usando .iloc
Para selecionar um segmento de linhas, usamos dois inteiros de índice de linha especificados separados por dois pontos. Agora, precisamos prestar atenção à exclusividade mencionada anteriormente.
Podemos pegar a linha df.iloc[1:4]
como exemplo para ilustrar este conceito. O número do índice 1 significa a segunda linha, então nosso segmento começa lá. O inteiro do índice 4 representa a quinta linha – mas como .iloc
não é inclusivo para seleção de segmento, nossa saída incluirá todas as linhas até a última antes desta. Portanto, retornará a segunda, terceira e quarta linha.
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 |
Selecionar 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 podermos prosseguir para o column_indexer
. Para recuperar os valores da terceira coluna de df
para cada linha, digitamos df.iloc[:, 2]
.
Como Region
é a terceira coluna no 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 várias colunas usando .iloc
Para selecionar várias 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 colunas.
No nosso caso, as informações exibidas são o Nome
e 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 uma fatia de colunas usando .iloc
Para a seleção de fatias usando .iloc
, a lógica do column_indexer
segue a do row_indexer
. A coluna representada pelo inteiro após os dois pontos não está incluída na saída. Para recuperar a segunda e terceira colunas, a linha de código deve parecer com isso: 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 |
Pakistan |
Á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 tanto uma única célula quanto um sub-DataFrame. Para retornar a única célula na interseção da linha 3 e coluna 4, digitamos df.iloc[2, 3]
.
Assim como com .loc
, podemos especificar ambos os índices como listas usando 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
Em geral, há uma regra simples a seguir onde a escolha do método depende do 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 .loc
ou .iloc
por natureza. Por exemplo, iterar sobre linhas ou colunas é mais fácil e intuitivo usando 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 que favorecem .loc |
Cenários que favorecem .iloc |
Seu DataFrame tem nomes de índice/coluna significativos. |
Você está iterando sobre linhas/colunas pela sua posição. |
Você precisa filtrar com base em condições sobre os 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 problemas possíveis. Um erro comum ao usar .loc
é encontrar um KeyError
. Este erro ocorre quando tentamos acessar um rótulo de linha ou coluna que não existe dentro do nosso DataFrame. Para evitar isso, sempre devemos garantir que os rótulos que estamos usando sejam precisos e que correspondam aos rótulos existentes no seu DataFrame e verificar se há erros de digitação.
Além disso, é importante sempre usar aspas para os rótulos especificados usando .loc
. Esquecê-las 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 saber mais, aqui estão alguns bons próximos passos: