Qual a diferença entre iloc, ix e loc?
Alguém pode explicar como esses três métodos de fatiar são diferentes?
Eu já vi os documentos e essas respostas , mas ainda me encontro incapaz de explicar como os três são diferentes. Para mim, eles parecem intercambiáveis ​​em grande parte, porque estão nos níveis mais baixos de fatiamento.
Por exemplo, digamos que queremos obter as cinco primeiras linhas de a DataFrame. Como é que todos esses três funcionam?
Alguém pode apresentar três casos em que a distinção de usos é mais clara?
— AZhao
muito importante mencionar os cenários SettingWithCopyWarning: stackoverflow.com/questions/20625582/… e stackoverflow.com/questions/23688307/…
Observe que o ix agora está planejado para descontinuação: github.com/pandas-dev/pandas/issues/14218
Nota: no pandas versão 0.20.0 e superior, ixestá obsoleto e o uso de loce ilocé incentivado. Deixei as partes desta resposta que descrevem ixintactas como uma referência para usuários de versões anteriores do pandas. Exemplos foram adicionados abaixo, mostrando alternativas para ix .
Primeiro, aqui está uma recapitulação dos três métodos:
locobtém linhas (ou colunas) com rótulos específicos do índice.
ilocobtém linhas (ou colunas) em posições específicas no índice (portanto, são necessários números inteiros).
ixgeralmente tenta se comportar como, locmas volta a se comportar como ilocse um rótulo não estivesse presente no índice.
É importante observar algumas sutilezas que podem ser ixum pouco complicadas de usar:
se o índice for do tipo inteiro, ixusará apenas a indexação baseada em rótulo e não voltará à indexação baseada em posição. Se o rótulo não estiver no índice, um erro será gerado.
se o índice não contiver apenas números inteiros, um número inteiro ixusará imediatamente a indexação baseada em posição em vez da indexação baseada em rótulo. Se, no entanto, ixreceber outro tipo (por exemplo, uma string), ele poderá usar a indexação baseada em rótulo.
Para ilustrar as diferenças entre os três métodos, considere a seguinte série:
Veremos fatiar com o valor inteiro 3.
Nesse caso, s.iloc[:3]retorna as 3 primeiras linhas (já que trata 3 como uma posição) e s.loc[:3]retorna as 8 primeiras linhas (já que trata 3 como um rótulo):
Aviso s.ix[:3]retorna a mesma série ques.loc[:3] uma vez que procura primeiro o rótulo em vez de trabalhar na posição (e o índice para sé do tipo inteiro).
E se tentarmos com um rótulo inteiro que não esteja no índice (por exemplo, 6 )?
Aqui s.iloc[:6]retorna as 6 primeiras linhas da série conforme o esperado. No entanto, s.loc[:6]gera um KeyError, pois 6não está no índice.
De acordo com as sutilezas mencionadas acima, s.ix[:6]agora gera um KeyError porque ele tenta funcionar como locmas não consegue encontrar um 6no índice. Como nosso índice é do tipo inteiroix ele não volta a se comportar comoiloc .
Se, no entanto, nosso índice fosse do tipo misto, dado que um número inteiro ixse comportaria como ilocimediatamente, em vez de gerar um KeyError:
Lembre-se de que ixainda é possível aceitar números não inteiros e se comportar da seguinte maneira loc:
Como orientação geral, se você estiver indexando apenas usando rótulos ou indexando apenas com posições inteiras, use locou ilocevite resultados inesperados - tente não usar ix.
Combinando indexação baseada em posição e baseada em rótulo
Às vezes, com um DataFrame, você desejará combinar métodos de indexação de rótulo e de posição para as linhas e colunas.
Por exemplo, considere o seguinte DataFrame. Qual a melhor forma de dividir as linhas até e incluindo 'c' e pegar as quatro primeiras colunas?
Nas versões anteriores do pandas (antes da versão 0.20.0), ixvocê pode fazer isso de maneira bem organizada - podemos dividir as linhas por rótulo e as colunas por posição (observe que, para as colunas, ixo padrão será o faturamento baseado em posição, pois 4não é um nome de coluna ):
Nas versões posteriores dos pandas, podemos alcançar esse resultado usando iloce com a ajuda de outro método:
get_loc()é um método de índice que significa "obter a posição do rótulo neste índice". Observe que, desde o corte comiloc é exclusivo de seu ponto de extremidade, devemos adicionar 1 a esse valor se quisermos a linha 'c' também.
Existem outros exemplos na documentação dos pandas aqui .
Ótima explicação! Uma pergunta relacionada que eu sempre tive é que relação, se houver, loc, iloc e ix tem com os avisos SettingWithCopy? Há alguma documentação, mas para ser honesto eu ainda estou um pouco confuso pandas.pydata.org/pandas-docs/stable/...
— measureallthethings
@measureallthethings: loc, iloce ixainda pode acionar o aviso se eles são encadeados. O uso do exemplo DataFrame nos documentos vinculados dfmi.loc[:, 'one'].loc[:, 'second']aciona o aviso da mesma maneira dfmi['one']['second']que uma cópia dos dados (em vez de uma exibição) pode ser retornada pela primeira operação de indexação.
O que você usa se deseja pesquisar um DateIndex com uma Data ou algo parecido df.ix[date, 'Cash']?
— Cjm2671
@ cjm2671: ambos locou ixdevem funcionar nesse caso. Por exemplo, df.loc['2016-04-29', 'Cash']retornará todos os índices de linha com essa data específica na coluna 'Caixa'. (Você pode ser o mais específico possível ao recuperar índices com seqüências de caracteres, por exemplo '2016-01', selecionará todas as datas em janeiro de 2016, `` 2016-01-02 11 'selecionará as datas em 2 de janeiro de 2016 com o horário 11: ??: ?? .)
Caso você queira atualizar esta resposta em algum momento, há sugestões aqui de como usar o loc / iloc em vez de ix github.com/pandas-dev/pandas/issues/14218
ilocfunciona com base no posicionamento inteiro. Portanto, não importa quais sejam seus rótulos de linha, você sempre pode, por exemplo, obter a primeira linha fazendo
ou as últimas cinco linhas, fazendo
Você também pode usá-lo nas colunas. Isso recupera a terceira coluna:
Você pode combiná-los para obter interseções de linhas e colunas:
Por outro lado, .locuse índices nomeados. Vamos configurar um quadro de dados com seqüências de caracteres como rótulos de linha e coluna:
Então podemos obter a primeira linha por
e as segundas duas linhas da 'date'coluna por
e assim por diante. Agora, vale a pena ressaltar que os índices padrão de linha e coluna para a DataFramesão números inteiros de 0 e, nesse caso, iloce locfuncionariam da mesma maneira. É por isso que seus três exemplos são equivalentes. Se você tivesse um índice não numérico, como seqüências de caracteres ou data / hora, isso df.loc[:5] geraria um erro.
Além disso, você pode fazer a recuperação da coluna apenas usando os quadros de dados __getitem__:
Agora, suponha que você queira misturar a posição e a indexação nomeada, ou seja, indexar usando nomes em linhas e posições em colunas (para esclarecer, quero dizer, selecione em nosso quadro de dados, em vez de criar um quadro de dados com seqüências de caracteres no índice de linha e números inteiros em o índice da coluna). É aqui que .ixentra:
Também acho que vale a pena mencionar que você também pode passar vetores booleanos para o locmétodo. Por exemplo:
Retornará a primeira e a terceira linhas de df. Isso é equivalente a df[b]seleção, mas também pode ser usado para atribuir via vetores booleanos:
— JoeCondron
O df.iloc [:,:] é equivalente a todas as linhas e colunas?
— Alvis
É como seria df.loc[:, :]. Pode ser usado para reatribuir os valores do todo DataFrameou criar uma visualização dele.
— 21317 JoeCondron
oi, você sabe por que loc e iloc levam parâmetros entre parênteses quadrados [] e não como um método normal entre parênteses clássicos ()?
— Marine Galantin
Na minha opinião, a resposta aceita é confusa, pois usa um DataFrame com apenas valores ausentes. Também não gosto do termo baseado em posição.iloc e prefiro local inteiro , pois é muito mais descritivo e exatamente o que .ilocsignifica. A palavra-chave é INTEGER - .ilocprecisa de INTEGERS.
Veja minha série de blogs extremamente detalhada sobre seleção de subconjuntos para mais
.ix está obsoleto e ambíguo e nunca deve ser usado
Como .ixestá obsoleto, focaremos apenas nas diferenças entre .loce .iloc.
Antes de falarmos sobre as diferenças, é importante entender que os DataFrames têm rótulos que ajudam a identificar cada coluna e cada índice. Vamos dar uma olhada em um exemplo de DataFrame:
Todas as palavras em negrito são os rótulos. As etiquetas, age, color, food, height, scoree statesão usados para as colunas . Os outros rótulos, Jane, Nick, Aaron, Penelope, Dean, Christina, Corneliasão usados para o índice .
As principais maneiras de selecionar linhas específicas em um DataFrame são com os indexadores .loce .iloc. Cada um desses indexadores também pode ser usado para selecionar colunas simultaneamente, mas é mais fácil focar apenas nas linhas por enquanto. Além disso, cada um dos indexadores usa um conjunto de colchetes que seguem imediatamente seu nome para fazer suas seleções.
.loc seleciona dados apenas por rótulos
Primeiro falaremos sobre o .locindexador, que seleciona apenas os dados pelos rótulos do índice ou da coluna. Em nosso exemplo DataFrame, fornecemos nomes significativos como valores para o índice. Muitos DataFrames não terão nomes significativos e, em vez disso, usarão como padrão apenas os números inteiros de 0 a n-1, onde n é o comprimento do DataFrame.
Existem três entradas diferentes que você pode usar para .loc
Uma lista de strings
Notação de fatia usando cadeias como valores de início e parada
Selecionando uma única linha com .loc com uma sequência
Para selecionar uma única linha de dados, coloque o rótulo do índice dentro dos colchetes a seguir .loc.
Isso retorna a linha de dados como uma série
Selecionando várias linhas com .loc com uma lista de cadeias
Isso retorna um DataFrame com as linhas na ordem especificada na lista:
Selecionando várias linhas com .loc com notação de fatia
A notação de fatia é definida pelos valores de início, parada e etapa. Ao fatiar por etiqueta, os pandas incluem o valor de parada no retorno. As seguintes fatias de Aaron a Dean, inclusive. Seu tamanho da etapa não é definido explicitamente, mas o padrão é 1.
Fatias complexas podem ser obtidas da mesma maneira que as listas Python.
.iloc seleciona dados apenas por localização inteira
Vamos agora voltar para .iloc. Cada linha e coluna de dados em um DataFrame tem um local inteiro que o define. Isso é um acréscimo ao rótulo que é exibido visualmente na saída . O local inteiro é simplesmente o número de linhas / colunas da parte superior / esquerda começando em 0.
Existem três entradas diferentes que você pode usar para .iloc
Uma lista de números inteiros
Notação de fatia usando números inteiros como valores inicial e final
Selecionando uma única linha com .iloc com um número inteiro
Isso retorna a 5ª linha (local inteiro 4) como uma Série
Selecionando várias linhas com .iloc com uma lista de números inteiros
Isso retorna um DataFrame da terceira e da segunda à última linhas:
Selecionando várias linhas com .iloc com notação de fatia
Seleção simultânea de linhas e colunas com .loc e .iloc
Uma excelente capacidade de ambos .loc/.ilocé a capacidade de selecionar linhas e colunas simultaneamente. Nos exemplos acima, todas as colunas foram retornadas de cada seleção. Podemos escolher colunas com os mesmos tipos de entradas que fazemos para linhas. Simplesmente precisamos separar a seleção de linha e coluna com uma vírgula .
Por exemplo, podemos selecionar as linhas Jane e Dean com apenas as colunas altura, pontuação e estado da seguinte maneira:
Isso usa uma lista de rótulos para as linhas e notação de fatia para as colunas
Naturalmente, podemos realizar operações semelhantes .ilocusando apenas números inteiros.
Seleção simultânea com rótulos e localização de número inteiro
.ixfoi usado para fazer seleções simultaneamente com rótulos e local inteiro, o que foi útil, mas às vezes confuso e ambíguo e, felizmente, foi preterido. No caso de você precisar fazer uma seleção com uma mistura de rótulos e locais inteiros, será necessário fazer os rótulos de seleção ou locais inteiros.
Por exemplo, se quisermos selecionar linhas Nicke, Corneliajuntamente com as colunas 2 e 4, poderíamos usar .locconvertendo os números inteiros em rótulos com o seguinte:
Ou, alternativamente, converta os rótulos de índice em números inteiros com o get_locmétodo index.
Seleção booleana
O indexador .loc também pode fazer a seleção booleana. Por exemplo, se estivermos interessados ​​em encontrar todas as linhas com idade acima de 30 e retornar apenas as colunas foode score, podemos fazer o seguinte:
Você pode replicar isso com, .ilocmas não pode transmitir uma série booleana. Você deve converter a série booleana em uma matriz numpy como esta:
Selecionando todas as linhas
É possível usar .loc/.ilocapenas para seleção de coluna. Você pode selecionar todas as linhas usando dois pontos como este:
O operador de indexação [], também pode selecionar linhas e colunas, mas não simultaneamente.
A maioria das pessoas conhece o objetivo principal do operador de indexação DataFrame, que é selecionar colunas. Uma cadeia de caracteres seleciona uma única coluna como uma série e uma lista de cadeias seleciona várias colunas como um DataFrame.
O uso de uma lista seleciona várias colunas
O que as pessoas estão menos familiarizadas é que, quando a notação de fatia é usada, a seleção acontece por rótulos de linha ou por local inteiro. Isso é muito confuso e algo que quase nunca uso, mas funciona.
A explicitação de .loc/.ilocpara selecionar linhas é altamente preferida. O operador de indexação sozinho não pode selecionar linhas e colunas simultaneamente.
— Ted Petrou
Uau, essa foi uma das explicações muito bem articuladas e lúcidas que eu já vi sobre um tópico de programação. O que você explicou no último sobre a indexação normal que funciona em linhas ou colunas é uma das razões pelas quais temos loc e iloc método. Me deparei com essa advertência no curso do datacamp. a.) O que df.columns e df.index retornam? É uma lista de strings? Se for uma lista, é permitido acessar dois elementos como este df.columns [[2,4]] em uma lista? b.) Posso chamar get_loc () em df.columns? c.) Por que precisamos chamar df ['age']> 30.values ​​no caso de iloc.
— Pragun 30/05/19
O melhor analista que eu já vi.
Esta é uma resposta muito boa, gostei de não entrar muito no ix, que é preterido e inútil mergulhar fundo. Obrigado.