2015-12-14 7 views
5

Ho notato una strana differenza tra loc e ix quando si sostituisce un DataFrame in Panda.Differenza imprevista tra loc e ix

import pandas as pd 

# Create a dataframe 
df = pd.DataFrame({'id':[10,9,5,6,8], 'x1':[10.0,12.3,13.4,11.9,7.6], 'x2':['a','a','b','c','c']}) 
df.set_index('id', inplace=True) 

df 
     x1 x2 
id   
10 10.0 a 
9 12.3 a 
5 13.4 b 
6 11.9 c 
8 7.6 c 


df.loc[[10, 9, 7]] # 7 does not exist in the index so a NaN row is returned 
df.loc[[7]] # KeyError: 'None of [[7]] are in the [index]' 
df.ix[[7]] # 7 does not exist in the index so a NaN row is returned 

Perché df.loc[[7]] gettare un errore durante df.ix[[7]] restituisce una riga con NaN? è un insetto? In caso contrario, perché loc e ix sono progettati in questo modo?

(Nota sto usando Pandas 0.17.1 su Python 3.5.1)

+0

Deciso che questo è molto probabilmente un bug. Archiviato un rapporto [qui] (https://github.com/pydata/pandas/issues/11840) – Ben

risposta

2

Come @shanmuga dice, questo è (almeno per loc) del previsto e il comportamento documentato, e non un bug.

La documentazione relativa loc/selezione per etichetta, fornisce le regole di questo (http://pandas.pydata.org/pandas-docs/stable/indexing.html#selection-by-label):

Almeno 1 delle etichette per i quali si chiede, deve essere nell'indice o un KeyError volontà essere cresciuto!

Ciò significa utilizzare loc con una singola etichetta (es df.loc[[7]]) genererà un errore se questa etichetta non è nell'indice, ma quando viene utilizzato con un elenco di etichette (es df.loc[[7,8,9]]) non genererà un errore se almeno una di quelle etichette è nell'indice.


Per ix io sono meno sicuro, e questo non è documentato chiaramente che penso. Ma in ogni caso, ix è molto più permissivo e ha un sacco di casi limite (ricaduta in posizione intera ecc.) Ed è piuttosto una tana di coniglio.Ma in generale, ix restituirà sempre un risultato indicizzato con le etichette fornite (quindi non controlla se le etichette si trovano nell'indice come fa loc), a meno che non sia l'indice di posizione intero.
Nella maggior parte dei casi si consiglia di utilizzare loc/iloc

+0

Ciò che è così confuso è che 'df.loc [[7,8,9]]' restituisce effettivamente una riga per id = 7, ma 'df.loc [[7]]' no. Mi sarei aspettato che entrambi o l'errore, o per 'df.loc [[7,8,9]]' per non restituire una riga per id = 7. Tuttavia, sono felice di sapere che questo non è un bug. Grazie per l'aiuto. – Ben

1

Penso che questo comportamento è destinato, non è un bug.
Anche se non sono riuscito a trovare alcuna documentazione ufficiale, ho trovato un commento da jreback il 21 marzo 2014 a issue on GitHub indicandolo.

ix può molto sottilmente dare risultati errati (utilizzare un indice di dire i numeri pari)

è possibile utilizzare qualsiasi funzione che si desidera; ix è ancora lì, ma non fornisce le garanzie che fornisce loc, cioè che non interpreterà un numero come posizione


quanto riguarda perché è progettato in modo
Come indicato in docs

.ix supporta l'intero misto e l'accesso basato su etichetta. È principalmente basato sull'etichetta, ma ricadrà sull'intero accesso posizionale a meno che l'asse corrispondente non sia di tipo intero.

A mio parere l'aumento di KeyError sarebbe ambiguo, sia che provenga dall'indice, sia dalla posizione intera. Invece ix restituisce NaN quando dato un elenco

+0

Ma allora perché 'df.loc [[7]]' restituisce un errore e 'df.loc [[10, 9, 7]] 'restituisce un dataframe con tre righe? Qual è lo scopo di questo? – Ben

+0

'.loc' fornisce una garanzia che i valori siano presenti nell'indice DataFrame. Tuttavia '.ix' non lo garantisce (controlla entrambi gli indici prima di tornare alla posizione intera). In questi casi (IMHO) è meglio dare 'NaN' invece di sollevare un errore chiave è meglio. – shanmuga

+0

Ancora, perché 'df.loc [[10, 9, 7]]' restituisce tre righe (ad esempio, una per id = 7 quando non esiste tale id) se '.loc' fornisce una garanzia come si menziona? – Ben