从列表或字典中写出任意大小的布尔表达式
Write a Boolean expression of arbitrary size from a list or dictionary
我正在处理 pandas 数据帧,这些数据帧具有一些统一的列标签模式,但列数是任意的。
例如,下面的 df 包含列 col_names,列的一个特殊子集,以及与这些特殊列对应的过滤条件。它们通过索引或字典链接,任您选择。
col_names = ['col1','col2','col3','xyz.1','xyz.2','xyz.3']
relevant_col_names = ['xyz.1', 'xyz.2', 'xyz.3']
filter_criteria = [something1, something2, something3]
我想获取子集数据帧,其中 'xyz.1' == something1 & 'xyz.2' == something2 & 'xyz.3' ==something3
我通常会这样做:
whatIwant = df.loc[df['xyz.1']==something1 & df['xyz.2']==something2 & df['xyz.3']==something3]
问题是我需要能够为任意数量的 'xyz' 列 编写该表达式,而无需手动编写上述表达式的代码。
例如,如果 df 恰好有 5 个相关列,如下所示:
['col1','col2','col3','xyz.1','xyz.2','xyz.3','xyz.4','xyz.5']
然后我需要自动写这样的东西:
whatIwant = df.loc[df['xyz.1']==something1 & df['xyz.2']==something2 & df['xyz.3']==something3 & df['xyz.4']==something4 & df['xyz.5']==something5]
有没有一种方法可以根据列表或字典(或其他东西)编写任意长度的布尔表达式,并在其中对其中的所有内容进行 ANDing?
我不知道如何为 google 表述这个问题。它似乎与列表和字典理解、表达式合成或其他内容有关。即使知道表达这个问题的正确方式,如何为 Whosebug 标记这个问题,and/or 我应该 google 也会很有帮助。谢谢!
假设你有一个列表中的所有“东西”,你可以这样做:
import functools
import operator
import pandas as pd
df = pd.DataFrame.from_dict({
"abc": (1, 2, 3),
"xyz.1": (4, 2, 7),
"xyz.2": (8, 5, 5)
})
targets = [2, 5]
filtered_dfs = (df[f"xyz.{index + 1}"] == target for index, target in enumerate(targets))
filtered_df = df.loc[functools.reduce(operator.and_, filtered_dfs)]
print(filtered_df)
我们通过 df[f"xyz.{index + 1}"] == target
在 filtered_dfs
中的 df
上构造每个过滤器。对于 targets
的第一次迭代,这将是 df["xyz.1"] == 2
。对于第二次迭代,它将是 df["xyz.2"] == 5
.
然后我们将所有这些过滤器与 functools.reduce(operator.and_, filtered_dfs)
结合起来,这就像 filtered_df_1 & filtered_df_2 & ...
.
我们最终通过 df.loc
将过滤器应用于数据框,这给出了此处在 xyz.1
中具有 2
且在 [=24= 中具有 5
的行].输出为:
abc xyz.1 xyz.2
1 2 2 5
我正在处理 pandas 数据帧,这些数据帧具有一些统一的列标签模式,但列数是任意的。
例如,下面的 df 包含列 col_names,列的一个特殊子集,以及与这些特殊列对应的过滤条件。它们通过索引或字典链接,任您选择。
col_names = ['col1','col2','col3','xyz.1','xyz.2','xyz.3']
relevant_col_names = ['xyz.1', 'xyz.2', 'xyz.3']
filter_criteria = [something1, something2, something3]
我想获取子集数据帧,其中 'xyz.1' == something1 & 'xyz.2' == something2 & 'xyz.3' ==something3
我通常会这样做:
whatIwant = df.loc[df['xyz.1']==something1 & df['xyz.2']==something2 & df['xyz.3']==something3]
问题是我需要能够为任意数量的 'xyz' 列 编写该表达式,而无需手动编写上述表达式的代码。
例如,如果 df 恰好有 5 个相关列,如下所示:
['col1','col2','col3','xyz.1','xyz.2','xyz.3','xyz.4','xyz.5']
然后我需要自动写这样的东西:
whatIwant = df.loc[df['xyz.1']==something1 & df['xyz.2']==something2 & df['xyz.3']==something3 & df['xyz.4']==something4 & df['xyz.5']==something5]
有没有一种方法可以根据列表或字典(或其他东西)编写任意长度的布尔表达式,并在其中对其中的所有内容进行 ANDing?
我不知道如何为 google 表述这个问题。它似乎与列表和字典理解、表达式合成或其他内容有关。即使知道表达这个问题的正确方式,如何为 Whosebug 标记这个问题,and/or 我应该 google 也会很有帮助。谢谢!
假设你有一个列表中的所有“东西”,你可以这样做:
import functools
import operator
import pandas as pd
df = pd.DataFrame.from_dict({
"abc": (1, 2, 3),
"xyz.1": (4, 2, 7),
"xyz.2": (8, 5, 5)
})
targets = [2, 5]
filtered_dfs = (df[f"xyz.{index + 1}"] == target for index, target in enumerate(targets))
filtered_df = df.loc[functools.reduce(operator.and_, filtered_dfs)]
print(filtered_df)
我们通过 df[f"xyz.{index + 1}"] == target
在 filtered_dfs
中的 df
上构造每个过滤器。对于 targets
的第一次迭代,这将是 df["xyz.1"] == 2
。对于第二次迭代,它将是 df["xyz.2"] == 5
.
然后我们将所有这些过滤器与 functools.reduce(operator.and_, filtered_dfs)
结合起来,这就像 filtered_df_1 & filtered_df_2 & ...
.
我们最终通过 df.loc
将过滤器应用于数据框,这给出了此处在 xyz.1
中具有 2
且在 [=24= 中具有 5
的行].输出为:
abc xyz.1 xyz.2
1 2 2 5