如何根据部分匹配选择 DataFrame 列?

Posted

技术标签:

【中文标题】如何根据部分匹配选择 DataFrame 列?【英文标题】:How to select DataFrame columns based on partial matching? 【发布时间】:2015-10-11 15:16:49 【问题描述】:

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

我一直在为nd.arrays / pd.series 寻找类似containsisin 的东西,但没有成功。

这让我很沮丧,因为我已经在检查 DataFrame 的列中是否出现了特定的字符串模式,例如:

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

但是,无论我怎么敲头,我都无法将.str.contains() 应用于df.columns 返回的对象——这是一个Index——也不是df.columns.values 返回的对象——这是一个@987654331 @。不过,这对于“切片”操作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]]

当然,在第一个解决方案中,我可以执行相同类型的正则表达式检查,因为我可以将其应用于迭代返回的 str 数据类型。

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

我很想知道您对此有何看法,以及可能的替代方案。鉴于我的菜鸟水平,如果您能纠正我在代码中可能犯的任何错误并指出正确的方向,我将不胜感激。

谢谢, 米歇尔

编辑:我刚刚找到了 Index 方法 Index.to_series(),它返回 - ehm - 我可以应用 .str.contains('whatever')Series。 但是,这不如真正的正则表达式强大,而且我找不到将Index.to_series().str 的结果传递给re.search() 函数的方法..

【问题讨论】:

注:系列过滤器支持正则表达式 【参考方案1】:

通过部分字符串选择列,可以简单地通过:

df.filter(like='hello')  # select columns which contain the word hello

并且要通过部分字符串匹配来选择行,您可以将axis=0传递给过滤器:

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

【讨论】:

【参考方案2】:

您使用map 的解决方案非常好。如果您真的想使用 str.contains,可以将 Index 对象转换为 Series(具有 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

更新我刚刚读了你的最后一段。从documentation,str.contains 允许您默认传递正则表达式 (str.contains('^myregex'))

【讨论】:

只要df.loc[:, df.columns.str.contains('x')] 也可以。 @Robert Smith 更新是最有用的。我对它进行了更多研究,发现了两件事。设置case=False 进行不区分大小写的搜索,设置regex=True 使用正则表达式。示例:df.loc[:, df.columns.str.contains('x', case=False, regex=True)]【参考方案3】:

我认为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'

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

【讨论】:

以上是关于如何根据部分匹配选择 DataFrame 列?的主要内容,如果未能解决你的问题,请参考以下文章

如何根据列值从 DataFrame 中选择行?

如何根据列值从 DataFrame 中选择行?

Spark Dataframe 中的过滤操作

如何根据另一列的值从 Spark DataFrame 中选择特定列?

R Dataframe:根据其他2个列匹配对未定义的num列求和

pandas表连接