没有 KeyError 的 Pandas .loc

Ale*_*ail 15 pandas

>>> 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. 
Run Code Online (Sandbox Code Playgroud)

我想要在任何一个都不会失败的东西

>>> pd.DataFrame([1], index=['1']).loc['2']  # KeyError
>>> pd.DataFrame([1], index=['1']).loc[['2']]  # KeyError
Run Code Online (Sandbox Code Playgroud)

是否有类似的函数loc可以优雅地处理这个问题,或者有其他表达这个查询的方式?

Jos*_*osh 8

更新@AlexLenail 评论
对于大型列表来说这会很慢,这是一个公平的观点。我做了更多的挖掘,发现intersection方法可用于Indexes列。我不确定算法的复杂性,但根据经验它要快得多。

你可以做这样的事情。

good_keys = df.index.intersection(all_keys)
df.loc[good_keys]
Run Code Online (Sandbox Code Playgroud)

或者像你的例子

df = pd.DataFrame([1], index=['1'])
df.loc[df.index.intersection(['2'])]
Run Code Online (Sandbox Code Playgroud)

下面是一个小实验

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)
Run Code Online (Sandbox Code Playgroud)

原答案

我不确定 Pandas 是否有一个内置函数来处理这个问题,但你可以使用 Python 列表理解来过滤到有效的索引。

给定一个数据帧 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
Run Code Online (Sandbox Code Playgroud)

您可以使用此过滤索引查询

keys = ['test', 'train', 'try', 'fake', 'broken']
valid_keys = [key for key in keys if key in df2.index.values]
df2.loc[valid_keys]
Run Code Online (Sandbox Code Playgroud)

如果您使用df2.columns而不是,这也适用于列df2.index.values