Python使用列表中的项目迭代创建过滤器表达式

标签 python pandas dataframe list-comprehension

我想使用列表中的所有项目创建过滤表达式,以便我可以查询 pandas 数据框。

请使用下面的示例代码:

col = ['A','B']
data = [[0,5],[3,2],[1,9],[2,7]]
df = pd.DataFrame(data, columns=col)

fltr = [('A', 1),
 ('A', 1, 'B', 5)]

我想在循环中重写下面的代码,这样我就不需要自己编写所有可能的组合:

f = ['{0}>={1}'.format(fltr[0][0], fltr[0][1])]
df.query(f)
f = ['{0}<={1}'.format(fltr[0][0], fltr[0][1])]
df.query(f)
f = ['{0}>={1} and {2}>={3}'.format(fltr[1][0], fltr[1][1], fltr[1][2], fltr[1][3])]
df.query(f)
...

另请注意,我想查询每个表达式的“>=”和“<=”的每个组合

所需的表达方式:

A>=1, A<=1, A>=1 and B>=5, A>=1 and B<=5, A<=1 and B>=5, A<=1 and B<=5

最佳答案

您将需要多个部件才能获得您想要的结果。您需要一个函数将元组拆分为一系列 2 元组。 itertools 包中的 product 函数可以处理创建列、操作和值的组合。然后,您可以对列进行分组,并再次使用产品来获取所有过滤器组合。之后,您可以使用 .join 合并字符串并将过滤器传递给 df.evaldf.query

import pandas as pd
from itertools import product, groupby

ge, le = '>=', '<='

def split_tuple(tup):
    return [tup[i:i+2] for i in range(0, len(tup), 2)]

def create_basic_filters(tup):
    f_gen = product(split_tuple(tup), (ge, le))
    return [f'{col}{op}{v}' for (col, v), op in f_gen]

def create_filter_groups(basic_filters):
    gb = groupby(basic_filters, key=lambda x: x[:x.find('=')-1])
    groupings = [tuple(g) for _, g in gb]
    return [' & '.join(f) for f in product(*groupings)]


# test the filter creation
fltr = [('A', 1), ('A', 2, 'B', 3), ('A', 1, 'B', 5, 'C', 7), 
        ('A', 0, 'B', 2, 'C', 10, 'D', 15)]

basic_filters = create_basic_filters(fltr[2])
filter_strs = create_filter_groups(basic_filters)
filter_strs
# returns:
['A>=1 & B>=5 & C>=7',
 'A>=1 & B>=5 & C<=7',
 'A>=1 & B<=5 & C>=7',
 'A>=1 & B<=5 & C<=7',
 'A<=1 & B>=5 & C>=7',
 'A<=1 & B>=5 & C<=7',
 'A<=1 & B<=5 & C>=7',
 'A<=1 & B<=5 & C<=7']

要实际使用过滤器,我们可以将它们传递给 df.eval 以获取 bool 系列,或者如果您还想对数据帧进行切片,则传递给 df.query 。下面我们使用 for 循环打印每个数据帧的结果切片。

df = pd.DataFrame({'A': [0, 3, 1, 2],
                   'B': [5, 2, 9, 5],
                   'C': [3, 7, 11, 5],
                   'D': [12, 21, 13, 19]})

for f in filter_strs:
    print('='*30)
    print('Filter =', f)
    print(df.query(f))

# prints:
==============================
Filter = A>=1 & B>=5 & C>=7
   A  B   C   D
2  1  9  11  13
==============================
Filter = A>=1 & B>=5 & C<=7
   A  B  C   D
3  2  5  5  19
==============================
Filter = A>=1 & B<=5 & C>=7
   A  B  C   D
1  3  2  7  21
==============================
Filter = A>=1 & B<=5 & C<=7
   A  B  C   D
1  3  2  7  21
3  2  5  5  19
==============================
Filter = A<=1 & B>=5 & C>=7
   A  B   C   D
2  1  9  11  13
==============================
Filter = A<=1 & B>=5 & C<=7
   A  B  C   D
0  0  5  3  12
==============================
Filter = A<=1 & B<=5 & C>=7
Empty DataFrame
Columns: [A, B, C, D]
Index: []
==============================
Filter = A<=1 & B<=5 & C<=7
   A  B  C   D
0  0  5  3  12

关于Python使用列表中的项目迭代创建过滤器表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59447437/

相关文章:

python - 从在错误目录中创建的 latex 代码生成的 pdf 文件 - Python

python-3.x - Opencv - 将图像置于窗口中心

python - Pandas 将第二个最小值分配给列

python - 如何均衡 panda 数据框中的结果

dataframe - 如何从字典创建数据框,其中每个项目都是 PySpark 中的一列

python - 将 pandas 数据帧下采样到任意长度

python - 为 Pandas 中的 n 个最大值生成虚拟变量

python - Pandas DataFrame.apply 对于 scipy.stats 来说非常慢

python - Seaborn 中的 FacetGrid 数据标签

python - 将两列数据框转换为多索引系列