如何在 python 中自动将条件组合在一起?
How to automatically group conditions together in python?
我正在尝试在 python 中自动将条件组合在一起。难点在于,如果有多个条件,比如100个条件,手工"AND"会很乏味。我如何使用循环来实现这一目标?
import pandas as pd
s1 = pd.Series([1,2,3,4,5,6])
s2 = pd.Series([5,6,7,8,9,10])
s3 = pd.Series([11,12,5,7,8,2])
df = pd.DataFrame({'A': s1,'B': s2,'C': s3})
condition1 = df['A'] > 3
condition2 = df['B'] > 6
condition3 = df['C'] > 5
# AND Operation ->>> Can be achieved with a loop?
select = condition1 & condition2 & condition3
您可以通过创建条件列表并使用 reduce
:
来实现它
from functools import reduce
conditions = [
df['A'] > 3,
df['B'] > 6,
df['C'] > 5,
]
total_condition = reduce(lambda x, y: x & y, conditions)
测试用例:
d = pd.DataFrame(np.random.randint(1, 5, (700000, 3)), columns=["a", "b", "c"])
conditions = [
d["a"] > 2,
d["c"] > 1,
d["b"] > 2,
]*100
使用reduce
:
from functools import reduce
%timeit reduce(lambda x, y: x & y, conditions)
> 547 ms ± 14.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
使用 np.concat
+ df.all()
:
%timeit pd.concat(conditions, axis=1).all(1)
> 4.19 s ± 367 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
注意几点:
- 您可以使用列表或字典来存储可变数量的变量。
- 您的布尔级数作为 NumPy 数组;因此,您可以组合一系列系列并使用
np.ndarray.all
(or pd.DataFrame.all
) 来计算它们的交集。
您可以将布尔系列列表与 NumPy 或 Pandas:
conditions = [df['A'] > 3,
df['B'] > 6,
df['C'] > 5]
# all equivalent
select = pd.concat(conditions, axis=1).all(axis=1)
select = np.logical_and.reduce(conditions)
select = np.array(conditions).all(axis=0)
print(select)
array([False, False, False, True, True, False], dtype=bool)
同样地,如果你想命名你的布尔过滤器,你可以使用字典:
conditions = {1: df['A'] > 3,
2: df['B'] > 6,
3: df['C'] > 5}
select = np.array(list(conditions.values())).all(axis=0)
性能基准测试
性能将非常依赖于数据,您还应该按照 尝试 reduce
并使用您的数据检查性能。
df = pd.concat([df]*1000)
conditions = [df['A'] > 3,
df['B'] > 6,
df['C'] > 5]
conditions = conditions*100
%timeit reduce(lambda x, y: x & y, conditions) # 104 ms per loop
%timeit np.logical_and.reduce(conditions) # 104 ms per loop
%timeit np.array(conditions).all(axis=0) # 99.4 ms per loop
%timeit pd.concat(conditions, axis=1).all(axis=1) # 34.6 ms per loop
我正在尝试在 python 中自动将条件组合在一起。难点在于,如果有多个条件,比如100个条件,手工"AND"会很乏味。我如何使用循环来实现这一目标?
import pandas as pd
s1 = pd.Series([1,2,3,4,5,6])
s2 = pd.Series([5,6,7,8,9,10])
s3 = pd.Series([11,12,5,7,8,2])
df = pd.DataFrame({'A': s1,'B': s2,'C': s3})
condition1 = df['A'] > 3
condition2 = df['B'] > 6
condition3 = df['C'] > 5
# AND Operation ->>> Can be achieved with a loop?
select = condition1 & condition2 & condition3
您可以通过创建条件列表并使用 reduce
:
from functools import reduce
conditions = [
df['A'] > 3,
df['B'] > 6,
df['C'] > 5,
]
total_condition = reduce(lambda x, y: x & y, conditions)
测试用例:
d = pd.DataFrame(np.random.randint(1, 5, (700000, 3)), columns=["a", "b", "c"])
conditions = [
d["a"] > 2,
d["c"] > 1,
d["b"] > 2,
]*100
使用reduce
:
from functools import reduce
%timeit reduce(lambda x, y: x & y, conditions)
> 547 ms ± 14.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
使用 np.concat
+ df.all()
:
%timeit pd.concat(conditions, axis=1).all(1)
> 4.19 s ± 367 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
注意几点:
- 您可以使用列表或字典来存储可变数量的变量。
- 您的布尔级数作为 NumPy 数组;因此,您可以组合一系列系列并使用
np.ndarray.all
(orpd.DataFrame.all
) 来计算它们的交集。
您可以将布尔系列列表与 NumPy 或 Pandas:
conditions = [df['A'] > 3,
df['B'] > 6,
df['C'] > 5]
# all equivalent
select = pd.concat(conditions, axis=1).all(axis=1)
select = np.logical_and.reduce(conditions)
select = np.array(conditions).all(axis=0)
print(select)
array([False, False, False, True, True, False], dtype=bool)
同样地,如果你想命名你的布尔过滤器,你可以使用字典:
conditions = {1: df['A'] > 3,
2: df['B'] > 6,
3: df['C'] > 5}
select = np.array(list(conditions.values())).all(axis=0)
性能基准测试
性能将非常依赖于数据,您还应该按照 reduce
并使用您的数据检查性能。
df = pd.concat([df]*1000)
conditions = [df['A'] > 3,
df['B'] > 6,
df['C'] > 5]
conditions = conditions*100
%timeit reduce(lambda x, y: x & y, conditions) # 104 ms per loop
%timeit np.logical_and.reduce(conditions) # 104 ms per loop
%timeit np.array(conditions).all(axis=0) # 99.4 ms per loop
%timeit pd.concat(conditions, axis=1).all(axis=1) # 34.6 ms per loop