按索引名称过滤数据框行

时间:2018-08-07 15:12:11

标签: python pandas dataframe

我有一个DataFrame,我想根据元素的索引名称放置元素

               col1  col2
entry_1          10    11
entry_2_test     12    13
entry_3          14    15
entry_4_test     16    17

基本上我想删除以_test结尾的

我知道如何选择它们:

df.filter(like='_test', axis=0)

               col1  col2
entry_2_test     12    13
entry_4_test     16    17

然后我实际上可以获得那些索引:

df.filter(like='_test', axis=0).index

entry_2_test
entry_4_test

最后,我可以删除这些索引,并使用过滤后的索引覆盖数据框。

df = df.drop(df.filter(like='_test', axis=0).index)
df

               col1  col2
entry_1          10    11
entry_3          14    15

我的问题是这是否是正确的过滤方法,或者有更有效的专用功能来做到这一点?

3 个答案:

答案 0 :(得分:5)

您可以反转str.endswith的结果:

In[13]:
df.loc[~df.index.str.endswith('_test')]

Out[13]: 
         col1  col2
entry_1    10    11
entry_3    14    15

或者切片最后5个字符,然后使用!=进行比较:

In[13]:
df.loc[df.index.str[-5:]!='_test']

Out[18]: 
         col1  col2
entry_1    10    11
entry_3    14    15

通过传递正则表达式模式来过滤不以filter结尾的行,仍然可以使用'_test'

In[25]:
df.filter(regex='.*[^_test]$', axis=0)

Out[25]: 
         col1  col2
entry_1    10    11
entry_3    14    15

@ user3483203指出,最好使用以下正则表达式:

df.filter(regex='.*(?<!_test)$', axis=0)

答案 1 :(得分:3)

使用filter regex

df.filter(regex='.*[^_test]$', axis=0)
Out[274]: 
         col1  col2
entry_1    10    11
entry_3    14    15

答案 2 :(得分:2)

您可以使用列表推导并将布尔值列表提供给pd.DataFrame.loc

虽然这似乎是反模式,但由于未对Pandas字符串方法进行特别优化,因此实际上更有效:

df2 = pd.concat([df]*10000)

%timeit df2.loc[[i[-5:] == '_test' for i in df2.index]]    # 11.7 ms per loop
%timeit df2.loc[[i.endswith('_test') for i in df2.index]]  # 13.3 ms per loop
%timeit df2[~(df2.index.str[-5:] == '_test')]              # 22.1 ms per loop
%timeit df2[~df2.index.str.endswith('_test')]              # 21.7 ms per loop