Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 熊猫:选择名称以X开头的所有列的最佳方式_Python_Pandas_Dataframe_Selection - Fatal编程技术网

Python 熊猫:选择名称以X开头的所有列的最佳方式

Python 熊猫:选择名称以X开头的所有列的最佳方式,python,pandas,dataframe,selection,Python,Pandas,Dataframe,Selection,我有一个数据帧: 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'

我有一个数据帧:

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],})
我想在以
foo.
开头的列中选择1的值。除了以下方法外,还有更好的方法吗

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]
答案应打印出如下数据框:

   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]
df.columns.map(lambda x: x.startswith('foo'))
df.loc[:, columns.startswith('foo')]

只需执行列表理解即可创建列:

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方法:

为了实现您想要的,您需要添加以下内容来过滤不符合
==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

既然pandas的索引支持字符串操作,那么选择以“foo”开头的列的最简单、最好的方法就是:

df.loc[:, df.columns.str.startswith('foo')]

或者,可以使用过滤列(或行)标签。要指定正则表达式以匹配以
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

我的解决方案。它的性能可能较慢:

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

选择所需条目的另一个选项是使用
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
,因此不会被选择

列的选择是使用如下布尔索引完成的:

   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]
df.columns.map(lambda x: x.startswith('foo'))
df.loc[:, columns.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

根据@EdChum的回答,您可以尝试以下解决方案:

df[df.columns[pd.Series(df.columns.str.contains(“foo”)]]
如果不是所有要选择的列都以
foo
开头,这将非常有用。此方法选择包含子字符串
foo
的所有列,并且可以将其放置在列名的任何位置


本质上,我将
.startswith()
替换为
.contains()
最简单的方法是直接在列名上使用str,不需要
pd.Series

df.loc[:,df.columns.str.startswith(“foo”)]

您可以在此处尝试使用正则表达式过滤掉以“foo”开头的列

df.filter(正则表达式=“^foo*”)

如果需要在列中包含字符串foo,那么

df.filter(regex='foo*')

这是合适的

对于下一步,您可以使用

df[df.filter(regex='^foo*')。value==1]


要过滤掉“foo*”列的一个值为1的行。

在我的例子中,我需要一个前缀列表

colsToScale=["production", "test", "development"]
dc[dc.columns[dc.columns.str.startswith(tuple(colsToScale))]]

我不喜欢其他解决方案要求我们两次引用数据帧;如果您只有一个名为
df
的帧,这可能没什么问题,但通常情况并非如此(您的实际名称可能要长得多)。让我们利用索引功能来减少键入,并使代码更具可读性。没有什么能阻止我们使用这样的东西:

   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]
df.columns.map(lambda x: x.startswith('foo'))
df.loc[:, columns.startswith('foo')]
因为索引器可以是任何
可调用的
。我们甚至可以将这个伪索引器分配给一个变量,并将其用于多个帧:

foo_columns = columns.startswith('foo')
df_1.loc[:, foo_columns]
df_2.loc[:, foo_columns]
我们甚至可以把它打印得很漂亮:

> foo_columns
<function __main__.PandasIndexer:columns.str.startswith(pat='foo')()>
所有这些都是简短的魔法代码:

from pandas import Series
from inspect import signature, Signature


class PandasIndexer:
    def __init__(self, axis_name, accessor='str'):
        """
        Args:
            - axis_name: `columns` or `index`
            - accessor: e.g. `str`, or `dt`
        """
        self._axis_name = axis_name
        self._accessor = accessor
        self._dummy_series = Series(dtype=object)

    def _create_indexer(self, attribute):
        dummy_accessor = getattr(self._dummy_series, self._accessor)
        dummy_attr = getattr(dummy_accessor, attribute)
        name = f'PandasIndexer:{self._axis_name}.{self._accessor}.{attribute}'

        def indexer_factory(*args, **kwargs):
            def indexer(df):
                axis = getattr(df, self._axis_name)
                accessor = getattr(axis, self._accessor)
                method = getattr(accessor, attribute)
                return method(*args, **kwargs)

            bound_arguments = signature(dummy_attr).bind(*args, **kwargs)
            indexer.__qualname__ = (
                name + str(bound_arguments).replace('<BoundArguments ', '')[:-1]
            )
            indexer.__signature__ = Signature()
            return indexer

        indexer_factory.__name__ = name
        indexer_factory.__qualname__ = name
        indexer_factory.__signature__ = signature(dummy_attr)
        return indexer_factory

    def __getattr__(self, attribute):
        return self._create_indexer(attribute)

    def __dir__(self):
        """Make it work with auto-complete in IPython"""
        return dir(getattr(self._dummy_series, self._accessor))


columns = PandasIndexer('columns')
来自熊猫导入系列的

从检查进口签名,签名
PandasIndexer类:
定义初始化(self,axis\u name,accessor='str'):
"""
Args:
-轴名称:`columns`或`index`
-存取器:例如'str'或'dt'`
"""
self.\u axis\u name=axis\u name
self.\u访问器=访问器
self.\u dummy\u series=series(数据类型=对象)
定义创建索引器(自身,属性):
虚拟存取器=getattr(自.\u虚拟\u系列,自.\u存取器)
dummy\u attr=getattr(dummy\u访问器,属性)
name=f'PandasIndexer:{self.\u axis\u name}.{self.\u accessor}.{attribute}'
def索引器工厂(*args,**kwargs):
def索引器(df):
axis=getattr(df,自身轴名称)
存取器=getattr(轴,自存取器)
方法=getattr(访问器,属性)
返回方法(*args,**kwargs)
绑定参数=签名(伪属性).bind(*args,**kwargs)
索引器。\uuuuqalname\uuuuuu=(

name+str(bound_arguments).replace('这是我来这里的答案,与问题标题相匹配。OP实际上想要的更像是“使用仅基于以x开头的列的筛选器选择行的最佳方式”。我实际上喜欢将其设置为
Column=PandasIndexer('列')
因此,很明显,我在玩魔术行为,而不是使用全局变量,如
df.loc[:,Column.startswith('foo')]
;这也让人想起SQLAlchemy(对使用这种ORM的人来说是直观的)。