通过一系列布尔掩码过滤一系列列表中的列表元素

时间:2018-12-16 15:00:14

标签: python pandas filter boolean series

我有两个系列,如下所示: 系列1具有str列表,而系列2中具有布尔表达式的numpy数组。

但是我有50,000行,我想查看基于布尔表达式的值,如

ser1 = pd.Series([[1, 2, 3], [4], [7, 8]])
ser2 = pd.Series([[True, False, True], [False], [True, True]])

ser1

0    [1, 2, 3]
1          [4]
2       [7, 8]
dtype: object

ser2

0    [True, False, True]
1                [False]
2           [True, True]
dtype: object

然后

Output=[1,3],[],[7,8],....

我尝试了两种方法,但无法正确构造它们,第一种方法在第二种方法不起作用时花费了太多时间。

output=[]
for i in range(len(Series1)):
output.append(Series1.apply(np.array)[i][Series2[i]])

output=[Series1.apply(lambda x: x[i]) for i in Series2]

您对我可以获取此输出有任何建议吗?
非常感谢。

1 个答案:

答案 0 :(得分:2)

ser1 = pd.Series([[1, 2, 3], [4], [7, 8]])
ser2 = pd.Series([[True, False, True], [False], [True, True]])

有两种方法可以实现,但我不建议使用apply。一种选择是zip使用numpy的布尔索引建立系列并进行过滤:

pd.Series([np.array(x)[y] for x, y in zip(ser1, ser2)])

0    [1, 3]
1        []
2    [7, 8]
dtype: object

如果您需要结果作为列表,请在末尾致电.tolist

output = pd.Series([list(np.array(x)[y]) for x, y in zip(ser1, ser2)]).tolist()
output
# [[1, 3], [], [7, 8]]

您还可以使它成为具有嵌套列表理解功能的纯python列表组合。

pd.Series([
    [i for i, j in zip(x, y) if j] for x, y in zip(ser1, ser2)])

0    [1, 3]
1        []
2    [7, 8]
dtype: object

我建议使用此 FOR SMALL LISTS ,因为将列表转换为numpy数组(如第一个解决方案一样)会产生大量开销。


如果扁平化列表是一种选择,则应考虑这样做,因为这可能是最快的选择。

from itertools import chain

ser3 = np.array(list(chain.from_iterable(ser1)))
ser4 = np.array(list(chain.from_iterable(ser2)))

ser3[ser4]
# array([1, 3, 7, 8])

不幸的是,您失去了输入的结构,但是如果这不是问题,那就是赢家。