没有KeyError的Pandas .loc

时间:2017-09-19 16:46:28

标签: pandas

node_modules

我希望

中的任何一个都不会失败
>>> 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. 

是否有一个像>>> pd.DataFrame([1], index=['1']).loc['2'] # KeyError >>> pd.DataFrame([1], index=['1']).loc[['2']] # KeyError 这样的函数可以优雅地处理这个问题,或者用其他方式来表达这个查询?

5 个答案:

答案 0 :(得分:2)

更新@AlexLenail评论
对于大型列表而言,这将是一个公平的观点。我做了一点点挖掘,并found intersection方法可用于Indexes和列。我不确定算法的复杂性,但它在经验上要快得多。

你可以这样做。

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

或者喜欢你的例子

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

下面是一个小实验

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)

原始回答

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

给定DataFrame 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

您可以使用此

过滤索引查询
keys = ['test', 'train', 'try', 'fake', 'broken']
valid_keys = [key for key in keys if key in df2.index.values]
df2.loc[valid_keys]

如果您使用df2.columns代替df2.index.values

,这也适用于列

答案 1 :(得分:0)

它对我来说似乎很好。我正在使用pandas版本0.20.3运行Python 3.5。

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

或者如果您想要排除NaN行:

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

答案 2 :(得分:0)

此页面https://pandas.pydata.org/pandas-docs/stable/indexing.html#deprecate-loc-reindex-listlike具有解决方案:

In [8]: pd.DataFrame([1], index=['1']).reindex(['2']) Out[8]: 0 2 NaN

答案 3 :(得分:0)

我找到了一个替代方法(前提是事先检查了df.empty)。你可以做这样的事情

df [df.index =='2']->返回具有匹配值的数据帧或空数据帧。

答案 4 :(得分:0)

使用@binjip答案中的示例数据框:

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']

从数据框中获取匹配的记录。 注意:数据帧索引必须唯一才能正常工作!

df.reindex(keys)
          distance  population
Alabama        0.0         4.8
Alaska       300.0         0.7
Arizona      600.0         6.4
Virginia       NaN         NaN

如果要省略丢失的键:

df.reindex(df.index.intersection(keys))
         distance  population
Alabama         0         4.8
Alaska        300         0.7
Arizona       600         6.4