当前位置: 首页 > 知识库问答 >
问题:

熊猫:是否可以使用任意长的布尔条件过滤数据帧?

滕项明
2023-03-14

如果您确切地知道如何过滤数据帧,那么解决方案很简单:

df[(df.A==1)

但是,如果您接受用户输入,并且事先不知道用户想要使用多少标准,该怎么办?例如,用户想要一个过滤后的数据帧,其中列[A,B,C]==1。有没有可能做这样的事情:

def filterIt(*args, value):
    return df[(df.*args == value)]

因此,如果用户调用filterIt(A,B,C,value=1),它将返回:

df[(df.A == 1) & (df.B == 1) & (df.C == 1)]

共有3个答案

慕晨
2023-03-14

谢谢你们的帮助。在发现df.query()后,我想出了类似于马吕斯的东西:

def makeQuery(cols, equivalence=True, *args):
operator = ' == ' if equivalence else ' != '
query = ''
for arg in args:
    for col in cols:
        query = query + "({}{}{})".format(col, operator, arg) + ' & '

return query[:-3]


query = makeQuery([A, B, C], False, 1, 2)

查询的内容是一个字符串:

(A != 1) & (B != 1) & (C != 1) & (A != 2) & (B != 2) & (C != 2) 

可以传递给df.query(query)的

胡元明
2023-03-14

这里有另一种方法。它更干净,性能更好,并且具有可以是空的优点(在这种情况下,返回整个数据帧)。

def filter(df, value, *columns):
    return df.loc[df.loc[:, columns].eq(value).all(axis=1)]

解释

  1. values=df.loc[:,columns]只选择我们感兴趣的列。
  2. masks=values.eq(value)给出一个布尔数据框,表示与目标值相等。
  3. mask=masks.all(axis=1)跨列应用AND(返回索引掩码)。请注意,对于OR,您可以使用掩码.any(axis=1)
  4. 返回df.loc[mask]将索引掩码应用于数据帧

演示

import numpy as np
import pandas as pd

df = pd.DataFrame(np.random.randint(0, 2, (100, 3)), columns=list('ABC'))

# both columns
assert np.all(filter(df, 1, 'A', 'B') == df[(df.A == 1) & (df.B == 1)])

# no columns
assert np.all(filter(df, 1) == df)

# different values per column
assert np.all(filter(df, [1, 0], 'A', 'B') == df[(df.A == 1) & (df.B == 0)])

备选方案

对于少量列(

from operator import and_

def filter(df, value, *columns):
    return df.loc[reduce(and_, (df[column] == value for column in columns))]

按键检索Series对象(df[列])比围绕列(df.loc[:,列])的子集构建DataFrame对象要快得多。

In [4]: %timeit df['A'] == 1
100 loops, best of 3: 17.3 ms per loop

In [5]: %timeit df.loc[:, ['A']] == 1
10 loops, best of 3: 48.6 ms per loop

然而,当处理更多的列时,这种加速变得可以忽略不计。瓶颈成为ANDIN掩码在一起,其中减少(and_,...)远远慢于熊猫内置的all(轴=1)

弓俊晖
2023-03-14

我认为最优雅的方法是使用df.query(),在这里您可以建立一个包含所有条件的字符串,例如:

import pandas as pd
import numpy as np

cols = {}
for col in ('A', 'B', 'C', 'D', 'E'):
    cols[col] = np.random.randint(1, 5, 20)
df = pd.DataFrame(cols)

def filter_df(df, filter_cols, value):
    conditions = []
    for col in filter_cols:
        conditions.append('{c} == {v}'.format(c=col, v=value))
    query_expr = ' and '.join(conditions)
    print('querying with: {q}'.format(q=query_expr))
    return df.query(query_expr)

输出示例(由于随机生成的数据,结果可能不同):

filter_df(df, ['A', 'B'], 1)
querying with: A == 1 and B == 1
    A  B  C  D  E
6   1  1  1  2  1
11  1  1  2  3  4
 类似资料:
  • 我有一个数据帧 是否有某种自定义筛选方法,可以让Python知道 说我要过滤,

  • 问题内容: 我正在尝试使用Pandas在几个条件下进行布尔索引。我原来的DataFrame称为。如果执行以下操作,将得到预期的结果: 但是,如果我这样做(我认为应该是等效的),则不会返回任何行: 知道导致差异的原因是什么? 问题答案: 使用是因为运算符优先级: 或者,在单独的行上创建条件: 样品 :

  • 我有一个熊猫数据框,大约有50列和

  • 我正在寻找通过以下条件过滤df的方法: 由创建的

  • 问题内容: 我需要使用字典来过滤数据帧,该字典的键是列名,值是我要过滤的值: 但是我想做些事情 但这会多次过滤数据帧,一次过滤一个值,而不是一次应用所有过滤器。有没有办法以编程方式进行? 编辑:一个例子: 给 但预期结果是 仅应选择最后一个。 问题答案: IIUC,您应该可以执行以下操作: 通过制作一个系列来与以下项目进行比较: 选择以下内容的相应部分: 查找它们匹配的位置: 查找它们 都 匹配的

  • 问题内容: 我有一个要点词典,说: 我想创建一个新字典,其中所有x和y值均小于5的点,即点“ a”,“ b”和“ d”。 根据这本书,每个字典都有该函数,该函数返回一个 元组列表: 所以我写了这个: 有没有更优雅的方式?我期待Python具有一些超棒的功能… 问题答案: 如今,在Python 2.7及更高版本中,您可以使用dict理解: 在Python 3中: