[英]Filtering a dataframe on dynamic columns and values Python Pandas?
目标是在具有各自独立值的动态列数上过滤 DataFrame。 为了实现这一点,我从字典中创建了一个过滤掩码,我每次都应该能够使用它。
然而,此过滤器掩码变成了一个字符串,因此提供了一个“KeyError”。 我的逻辑如何工作的一些例子。
import pandas as pd
# Create a list of dictionaries with the data for each row
data = [{'col1': 1, 'col2': 'a', 'col3': True, 'col4': 1.0},
{'col1': 2, 'col2': 'b', 'col3': False, 'col4': 2.0},
{'col1': 1, 'col2': 'c', 'col3': True, 'col4': 3.0},
{'col1': 2, 'col2': 'd', 'col3': False, 'col4': 4.0},
{'col1': 1, 'col2': 'e', 'col3': True, 'col4': 5.0}]
df = pd.DataFrame(data)
filter_dict = {'col1': 1, 'col3': True,}
def create_filter_query_for_df(filter_dict):
query = ""
for i, (column, values) in enumerate(filter_dict.items()):
if i > 0:
query += " & "
if isinstance(values,float) or isinstance(values,int):
query += f"(data['{column}'] == {values})"
else:
query += f"(data['{column}'] == '{values}')"
return query
df[create_filter_query_for_df(filter_dict)]
结果是:
KeyError: "(data['col1'] == 1) & (data['col3'] == True)"
问题是create_filter_query_for_df()
将返回一个字符串,它应该是布尔变量。 如果您将面具制作如下:
mask1 = "(data['col1'] == 1) & (data['col3'] == True)" # the same error is returned;
# However if you format as below, it provides a success
mask2 = (data['col1'] == 1) & (data['col3'] == True)
mask1 的类型将为 str。 mask2 的类型将是布尔值。
但是,我不能使用 bool(mask1) 因为那样我就不能再将它用作过滤条件。 我很困所以在这里需要一些帮助。
如果我在尝试使用过滤器时采取了完全错误的方法,我深表歉意,这对我来说似乎是一个非常合适的解决方案。
提前致谢!
基于mask2
的过滤结果如下:
mask2 = (df['col1'] == 1) & (df['col3'] == True)
df[mask2]
col1 col2 col3 col4
0 1 a True 1.0
2 1 c True 3.0
4 1 e True 5.0
要使用字符串获得相同的结果,我们可以像这样使用df.query
:
df.query('(col1 == 1) & (col3 == True)')
col1 col2 col3 col4
0 1 a True 1.0
2 1 c True 3.0
4 1 e True 5.0
请注意,所需的语法实际上有点不同。 因此,让我们简化您的函数以得到我们需要的字符串:
def create_filter_query_for_df(filter_dict):
list_pairs = [f"({col} == {val})" for col, val in filter_dict.items()]
query = ' & '.join(list_pairs)
# '(col1 == 1) & (col3 == True)'
return query
df.query(create_filter_query_for_df(filter_dict))
col1 col2 col3 col4
0 1 a True 1.0
2 1 c True 3.0
4 1 e True 5.0
替代方法
顺便说一句,如果您只使用&运算符,解决此问题的另一种方法如下:
pd.Series
并将它们用作pd.concat
的输入, axis
参数设置为1
。df.all
与axis
参数再次设置为1
以评估生成的临时df
中每一行的所有值是否都等于True
)。pd.Series
,我们可以用它来过滤df
。my_mask = (pd.concat([df[k].eq(v) for k, v in filter_dict.items()],
axis=1)
.all(axis=1))
df[my_mask]
col1 col2 col3 col4
0 1 a True 1.0
2 1 c True 3.0
4 1 e True 5.0
当然,如果您的实际需求稍微复杂一些,这种方法可能并不理想(或者:根本无法发挥作用)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.