pandas DataFrame 中布尔索引器的高效链接
Efficient chaining of boolean indexers in pandas DataFrames
我正在尝试非常有效地链接一个 变量 数量的布尔值 pandas 系列,以通过布尔索引用作 DataFrame 上的过滤器。
通常在处理多个布尔条件时,像这样链接它们
condition_1 = (df.A > some_value)
condition_2 = (df.B <= other_value)
condition_3 = (df.C == another_value)
full_indexer = condition_1 & condition_2 & condition_3
但是随着条件的变化,这会成为一个问题。
bool_indexers = [
condition_1,
condition_2,
...,
condition_N,
]
我已经尝试了一些可能的解决方案,但我相信它可以更有效地完成。
选项 1
遍历索引器并连续应用。
full_indexer = bool_indexers[0]
for indexer in bool_indexers[1:]:
full_indexer &= indexer
选项 2
放入 DataFrame 并计算行积。
full_indexer = pd.DataFrame(bool_indexers).product(axis=0)
选项 3
使用 numpy.product
(like in this answer) 并从结果中创建一个新系列。
full_indexer = pd.Series(np.prod(np.vstack(bool_indexers), axis=0))
这三种解决方案都有些低效,因为它们依赖于循环或强制您创建一个新对象(如果重复多次可能会很慢)。
可以更有效地完成吗?还是这样?
使用np.logical_and
:
import pandas as pd
import numpy as np
df = pd.DataFrame({'A': [0, 1, 2], 'B': [0, 1, 2], 'C': [0, 1, 2]})
m1 = df.A > 0
m2 = df.B <= 1
m3 = df.C == 1
m = np.logical_and.reduce([m1, m2, m3])
# OR m = np.all([m1, m2, m3], axis=0)
out = df[np.logical_and.reduce([m1, m2, m3])]
输出:
>>> pd.concat([m1, m2, m3], axis=1)
A B C
0 False True False
1 True True True
2 True False False
>>> m
array([False, True, False])
>>> out
A B C
1 1 1 1
我正在尝试非常有效地链接一个 变量 数量的布尔值 pandas 系列,以通过布尔索引用作 DataFrame 上的过滤器。
通常在处理多个布尔条件时,像这样链接它们
condition_1 = (df.A > some_value)
condition_2 = (df.B <= other_value)
condition_3 = (df.C == another_value)
full_indexer = condition_1 & condition_2 & condition_3
但是随着条件的变化,这会成为一个问题。
bool_indexers = [
condition_1,
condition_2,
...,
condition_N,
]
我已经尝试了一些可能的解决方案,但我相信它可以更有效地完成。
选项 1
遍历索引器并连续应用。
full_indexer = bool_indexers[0]
for indexer in bool_indexers[1:]:
full_indexer &= indexer
选项 2
放入 DataFrame 并计算行积。
full_indexer = pd.DataFrame(bool_indexers).product(axis=0)
选项 3
使用 numpy.product
(like in this answer) 并从结果中创建一个新系列。
full_indexer = pd.Series(np.prod(np.vstack(bool_indexers), axis=0))
这三种解决方案都有些低效,因为它们依赖于循环或强制您创建一个新对象(如果重复多次可能会很慢)。
可以更有效地完成吗?还是这样?
使用np.logical_and
:
import pandas as pd
import numpy as np
df = pd.DataFrame({'A': [0, 1, 2], 'B': [0, 1, 2], 'C': [0, 1, 2]})
m1 = df.A > 0
m2 = df.B <= 1
m3 = df.C == 1
m = np.logical_and.reduce([m1, m2, m3])
# OR m = np.all([m1, m2, m3], axis=0)
out = df[np.logical_and.reduce([m1, m2, m3])]
输出:
>>> pd.concat([m1, m2, m3], axis=1)
A B C
0 False True False
1 True True True
2 True False False
>>> m
array([False, True, False])
>>> out
A B C
1 1 1 1