问题:熊猫:选择所有名称以X开头的列的最佳方法
我有一个DataFrame:
import pandas as pd
import numpy as np
df = pd.DataFrame({'foo.aa': [1, 2.1, np.nan, 4.7, 5.6, 6.8],
'foo.fighters': [0, 1, np.nan, 0, 0, 0],
'foo.bars': [0, 0, 0, 0, 0, 1],
'bar.baz': [5, 5, 6, 5, 5.6, 6.8],
'foo.fox': [2, 4, 1, 0, 0, 5],
'nas.foo': ['NA', 0, 1, 0, 0, 0],
'foo.manchu': ['NA', 0, 0, 0, 0, 0],})
我想在以开头的列中选择1的值foo.
。除了以下以外,还有更好的方法吗:
df2 = df[(df['foo.aa'] == 1)|
(df['foo.fighters'] == 1)|
(df['foo.bars'] == 1)|
(df['foo.fox'] == 1)|
(df['foo.manchu'] == 1)
]
类似于写类似的东西:
df2= df[df.STARTS_WITH_FOO == 1]
答案应打印出如下所示的DataFrame:
bar.baz foo.aa foo.bars foo.fighters foo.fox foo.manchu nas.foo
0 5.0 1.0 0 0 2 NA NA
1 5.0 2.1 0 1 4 0 0
2 6.0 NaN 0 NaN 1 0 1
5 6.8 6.8 1 0 5 0 0
[4 rows x 7 columns]
回答 0
只需执行列表推导即可创建您的列:
In [28]:
filter_col = [col for col in df if col.startswith('foo')]
filter_col
Out[28]:
['foo.aa', 'foo.bars', 'foo.fighters', 'foo.fox', 'foo.manchu']
In [29]:
df[filter_col]
Out[29]:
foo.aa foo.bars foo.fighters foo.fox foo.manchu
0 1.0 0 0 2 NA
1 2.1 0 1 4 0
2 NaN 0 NaN 1 0
3 4.7 0 0 0 0
4 5.6 0 0 0 0
5 6.8 1 0 5 0
另一种方法是从列创建序列,并使用向量化str方法startswith
:
In [33]:
df[df.columns[pd.Series(df.columns).str.startswith('foo')]]
Out[33]:
foo.aa foo.bars foo.fighters foo.fox foo.manchu
0 1.0 0 0 2 NA
1 2.1 0 1 4 0
2 NaN 0 NaN 1 0
3 4.7 0 0 0 0
4 5.6 0 0 0 0
5 6.8 1 0 5 0
为了实现您想要的目标,您需要添加以下内容以过滤不符合您的==1
条件的值:
In [36]:
df[df[df.columns[pd.Series(df.columns).str.startswith('foo')]]==1]
Out[36]:
bar.baz foo.aa foo.bars foo.fighters foo.fox foo.manchu nas.foo
0 NaN 1 NaN NaN NaN NaN NaN
1 NaN NaN NaN 1 NaN NaN NaN
2 NaN NaN NaN NaN 1 NaN NaN
3 NaN NaN NaN NaN NaN NaN NaN
4 NaN NaN NaN NaN NaN NaN NaN
5 NaN NaN 1 NaN NaN NaN NaN
编辑
看到您想要复杂的答案后,确定为:
In [72]:
df.loc[df[df[df.columns[pd.Series(df.columns).str.startswith('foo')]] == 1].dropna(how='all', axis=0).index]
Out[72]:
bar.baz foo.aa foo.bars foo.fighters foo.fox foo.manchu nas.foo
0 5.0 1.0 0 0 2 NA NA
1 5.0 2.1 0 1 4 0 0
2 6.0 NaN 0 NaN 1 0 1
5 6.8 6.8 1 0 5 0 0
回答 1
既然熊猫的索引支持字符串操作,那么可以说选择以’foo’开头的列的最简单最好的方法就是:
df.loc[:, df.columns.str.startswith('foo')]
或者,您可以使用过滤列(或行)标签df.filter()
。要指定正则表达式以匹配以开头的名称foo.
:
>>> df.filter(regex=r'^foo\.', axis=1)
foo.aa foo.bars foo.fighters foo.fox foo.manchu
0 1.0 0 0 2 NA
1 2.1 0 1 4 0
2 NaN 0 NaN 1 0
3 4.7 0 0 0 0
4 5.6 0 0 0 0
5 6.8 1 0 5 0
要仅选择所需的行(包含1
)和列,可以使用loc
,使用filter
(或任何其他方法)选择列,使用any
:
>>> df.loc[(df == 1).any(axis=1), df.filter(regex=r'^foo\.', axis=1).columns]
foo.aa foo.bars foo.fighters foo.fox foo.manchu
0 1.0 0 0 2 NA
1 2.1 0 1 4 0
2 NaN 0 NaN 1 0
5 6.8 1 0 5 0
回答 2
最简单的方法是直接在列名上使用str,不需要 pd.Series
df.loc[:,df.columns.str.startswith("foo")]
回答 3
根据@EdChum的答案,您可以尝试以下解决方案:
df[df.columns[pd.Series(df.columns).str.contains("foo")]]
万一并非您要选择的所有列都以开头,这将非常有用foo
。此方法选择包含子字符串的所有列,foo
并且可以将其放置在列名称的任何位置。
本质上,我替换.startswith()
为.contains()
。
回答 4
我的解决方案。性能可能会变慢:
a = pd.concat(df[df[c] == 1] for c in df.columns if c.startswith('foo'))
a.sort_index()
bar.baz foo.aa foo.bars foo.fighters foo.fox foo.manchu nas.foo
0 5.0 1.0 0 0 2 NA NA
1 5.0 2.1 0 1 4 0 0
2 6.0 NaN 0 NaN 1 0 1
5 6.8 6.8 1 0 5 0 0
回答 5
选择所需条目的另一种方法是使用map
:
df.loc[(df == 1).any(axis=1), df.columns.map(lambda x: x.startswith('foo'))]
这将为您提供包含的行的所有列1
:
foo.aa foo.bars foo.fighters foo.fox foo.manchu
0 1.0 0 0 2 NA
1 2.1 0 1 4 0
2 NaN 0 NaN 1 0
5 6.8 1 0 5 0
该行选择是通过做
(df == 1).any(axis=1)
如@ajcr的答案,它为您提供:
0 True
1 True
2 True
3 False
4 False
5 True
dtype: bool
表示该行3
和4
不包含1
和不会被选中。
列的选择是使用布尔索引完成的,如下所示:
df.columns.map(lambda x: x.startswith('foo'))
在上面的示例中,此返回
array([False, True, True, True, True, True, False], dtype=bool)
因此,如果某列不是以开头foo
,False
则返回该列,因此未选择该列。
如果您只想返回包含1
-的所有行(如您期望的输出所示),则只需执行
df.loc[(df == 1).any(axis=1)]
哪个返回
bar.baz foo.aa foo.bars foo.fighters foo.fox foo.manchu nas.foo
0 5.0 1.0 0 0 2 NA NA
1 5.0 2.1 0 1 4 0 0
2 6.0 NaN 0 NaN 1 0 1
5 6.8 6.8 1 0 5 0 0
回答 6
您可以在此处尝试使用正则表达式来过滤以“ foo”开头的列
df.filter(regex='^foo*')
如果您需要在列中包含字符串foo,则
df.filter(regex='foo*')
将是适当的。
下一步,您可以使用
df[df.filter(regex='^foo*').values==1]
过滤掉“ foo *”列的值之一为1的行。
回答 7
就我而言,我需要一个前缀列表
colsToScale=["production", "test", "development"]
dc[dc.columns[dc.columns.str.startswith(tuple(colsToScale))]]