2015-07-21 84 views
2

今天下午我正在努力寻找一种方法来选择Pandas DataFrame的几列,方法是检查它们名称中的特定模式(标签?)的出现情况。如何根据部分匹配选择DataFrame列?

我一直在寻找类似containsisinnd.arrays/pd.series,但没有运气。

这我感到沮丧了不少,因为我已经检查我的DataFrame列特定字符串模式的出现,如:

hp = ~(df.target_column.str.contains('some_text') | df.target_column.str.contains('other_text')) 
df_cln= df[hp] 

但是,不管我怎么撞我的头,我可以对df.columns返回的对象不适用.str.contains() - 这是Index - 也不是由df.columns.values返回的对象 - 这是ndarray。这对于“切片”操作df[column_name],即Series返回的内容工作得很好。

我的第一个解决方案涉及到for环路和帮助列表的创建:

ll = [] 
for a in df.columns: 
    if a.startswith('start_exp1') | a.startswith('start_exp2'): 
    ll.append(a) 
df[ll] 

(一个可以应用任何str功能,当然)

然后,我发现map功能并得到了它与下面的代码工作:

import re 
sel = df.columns.map(lambda x: bool(re.search('your_regex',x)) 
df[df.columns[sel]] 

课程,我可以有PERFO第一方案的因为我可以将它应用于由迭代返回的str数据类型。

我对Python很新,从来没有真正编写过任何程序,所以我对速度/时间/效率不太熟悉,但我倾向于认为第二种方法 - 使用地图 - 可能会更快,除了查看更多优雅对我的未经训练的眼睛。

我很想知道你对它的看法,以及可能的替代方案。考虑到我的noobness级别,如果你能纠正我在代码中犯的任何错误,并指出我朝着正确的方向,我将非常感激。

感谢, 米歇尔

编辑:我刚刚发现了Index方法Index.to_series(),它返回 - EHM - 一个Series,而我可以申请.str.contains('whatever')。 然而,这并不像一个真正的正则表达式的强大,我找不到合格的Index.to_series().str结果到re.search()功能的方式..

+0

注:系列过滤器支持正则表达式 – yuval

回答

6

使用map您的解决方案是非常好的。如果你真的想用str.contains,有可能索引对象转换为系列(其中有str.contains法):

In [1]: df 
Out[1]: 
    x y z 
0 0 0 0 
1 1 1 1 
2 2 2 2 
3 3 3 3 
4 4 4 4 
5 5 5 5 
6 6 6 6 
7 7 7 7 
8 8 8 8 
9 9 9 9 

In [2]: df.columns.to_series().str.contains('x') 
Out[2]: 
x  True 
y False 
z False 
dtype: bool 

In [3]: df[df.columns[df.columns.to_series().str.contains('x')]] 
Out[3]: 
    x 
0 0 
1 1 
2 2 
3 3 
4 4 
5 5 
6 6 
7 7 
8 8 
9 9 

UPDATE我刚刚看了你的最后一段。从documentation,str.contains可以让你默认传递一个正则表达式(str.contains('^myregex')

0

我觉得df.keys().tolist()是你正在寻找的东西。

A tiny example: 

from pandas import DataFrame as df 

d = df({'somename': [1,2,3], 'othername': [4,5,6]}) 

names = d.keys().tolist() 

for n in names: 
    print n 
    print type(n) 

输出:

othername 
type 'str' 

somename 
type 'str' 

然后用你得到的字符串,你可以做你想做的任何字符串操作。

1

我只是想添加一个替代符号,它与Robert Smith的答案相同。我认为这是写得更清楚一些:

df.loc[:, df.columns.to_series().str.contains('x').tolist()]