2017-09-19 1 views
1
>>> pd.DataFrame([1], index=['1']).loc['2'] # KeyError 
>>> pd.DataFrame([1], index=['1']).loc[['2']] # KeyError 
>>> pd.DataFrame([1], index=['1']).loc[['1','2']] # Succeeds, as in the answer below. 

Ich möchte etwas, das entweder nicht vonPandas .loc ohne KeyError

>>> pd.DataFrame([1], index=['1']).loc['2'] # KeyError 
>>> pd.DataFrame([1], index=['1']).loc[['2']] # KeyError 

Gibt es eine Funktion wie loc fehlschlagen, die diese ordnungsgemäß behandelt oder eine andere Art und Weise diese Abfrage auszudrücken ?

Antwort

1

Update für @AlexLenail Kommentar
Es ist ein wichtiger Punkt, dass dies für große Listen langsam. Ich habe ein bisschen mehr graben und found, dass die intersection Methode für Indexes und Spalten verfügbar ist. Ich bin mir nicht sicher über die algorithmische Komplexität, aber es ist viel schneller empirisch.

Sie können so etwas tun.

good_keys = df.index.intersection(all_keys) 
df.loc[good_keys] 

Oder wie Ihr Beispiel ist

df = pd.DataFrame([1], index=['1']) 
df.loc[df.index.intersection(['2'])] 

hier ein kleines Experiment unter

n = 100000 

# Create random values and random string indexes 
# have the bad indexes contain extra values not in DataFrame Index 
rand_val = np.random.rand(n) 
rand_idx = [] 
for x in range(n): 
    rand_idx.append(str(x)) 

bad_idx = [] 
for x in range(n*2): 
    bad_idx.append(str(x)) 

df = pd.DataFrame(rand_val, index=rand_idx) 
df.head() 

def get_valid_keys_list_comp(): 
    # Return filtered DataFrame using list comprehension to filter keys 
    vkeys = [key for key in bad_idx if key in df.index.values] 
    return df.loc[vkeys] 

def get_valid_keys_intersection(): 
    # Return filtered DataFrame using list intersection() to filter keys 
    vkeys = df.index.intersection(bad_idx) 
    return df.loc[vkeys] 

%%timeit 
get_valid_keys_intersection() 
# 64.5 ms ± 4.53 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) 

%%timeit 
get_valid_keys_list_comp() 
# 6.14 s ± 457 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 

Ursprünglicher Antwort

Ich bin nicht sicher, ob Pandas ein eingebautes hat in Funktion, um dies zu handhaben, aber Sie können Python Listenverständnis zu filt verwenden äh zu gültigen Indizes mit so etwas.

Bei einem Datenrahmen df2

  A B  C D F 
test 1.0 2013-01-02 1.0 3 foo 
train 1.0 2013-01-02 1.0 3 foo 
test 1.0 2013-01-02 1.0 3 foo 
train 1.0 2013-01-02 1.0 3 foo 

Sie können Ihre Index Abfrage mit diesem

keys = ['test', 'train', 'try', 'fake', 'broken'] 
valid_keys = [key for key in keys if key in df2.index.values] 
df2.loc[valid_keys] 

filtern Dies wird auch für die Spalten arbeiten, wenn Sie df2.columns anstelle von df2.index.values

+0

Trotz der Tatsache, das funktioniert, gibt es keine Möglichkeit, dies selbst in Pandas zu tun? Dies könnte sehr teuer sein, wenn Sie einen großen Tisch und eine große Liste (n ** 2) betrachten. –

+0

@AlexLenail guter Gedanke; Ich verbrachte ein wenig Zeit mit dem Graben und fand eine alternative Lösung. – Josh

+0

Ich wünschte, es gäbe ein Makro für 'df.loc [df.index.intersection (list)]' –

0

Es scheint funktioniert gut für mich. Ich betreibe Python 3.5 mit Pandas Version 0.20.3.

import numpy as np 
import pandas as pd 

# Create dataframe 
data = {'distance': [0, 300, 600, 1000], 
     'population': [4.8, 0.7, 6.4, 2.9]} 
df = pd.DataFrame(data, index=['Alabama','Alaska','Arizona','Arkansas']) 

keys = ['Alabama', 'Alaska', 'Arizona', 'Virginia'] 

# Create a subset of the dataframe. 
df.loc[keys] 
      distance population 
Alabama  0.0   4.8 
Alaska  300.0   0.7 
Arizona  600.0   6.4 
Virginia  NaN   NaN 

Oder wenn Sie die NaN Zeile ausschließen möchten:

df.loc[keys].dropna() 
      distance population 
Alabama  0.0   4.8 
Alaska  300.0   0.7 
Arizona  600.0   6.4 
+0

Ja, diese Lösung funktioniert auch, aber wenn Sie bereits Zeilen mit allen 'NaN' haben, werden sie unbeabsichtigt gelöscht. – Josh