我有一个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
我的问题是这是否是正确的过滤方法,或者有更有效的专用功能来做到这一点?
答案 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