根据NumPy数组中的布尔从列表中选择值

qcuzuvrc  于 2022-11-10  发布在  其他
关注(0)|答案(3)|浏览(125)

对于数组b中的每个子列表,返回列表a中与b子列表中的正布尔位置相同的值(即WHERE True)。

import pandas as pd
import numpy as np

a = pd.Series([1, 3, 5, 7, 9])  # values to choose from
b = np.array([[False, True, False, True, False],  # based on bools
              [False, False, False, False, False]])

out = []
for i, v in enumerate(b):
    out.append([])
    for j in range(len(e)):
        if v[j]:
            out[i].append(a[j])

out = np.array(out)  # np.array([[3,7],[]])  # result

# In first sublist, True is on index 1 and 3 which corresponds to values 3 and 7.

# In second sublist, there is not True, hence empty.

上面的工作似乎太费力了,而且它可能没有使用 numpy 矢量化(它在处理大数据时速度很慢)。

sshcrbum

sshcrbum1#

您的Series是1d;b是2d数组。Series也有行索引,这是普通数组没有的。

In [70]: a.shape, b.shape
Out[70]: ((5,), (2, 5))

In [71]: a
Out[71]: 
0    1
1    3
2    5
3    7
4    9
dtype: int64

我们可以使用b的行,形状为(5,)的一维数组从a中选择元素:

In [72]: a[b[0,:]]
Out[72]: 
1    3
3    7
dtype: int64

In [73]: a[b[1,:]]
Out[73]: Series([], dtype: int64)

由于各行产生不同的长度结果,我们不能一步完成该选择。a[b]给出错误,(5,)和(2,)之间不匹配。
使用阵列版本的a可能更简单,也是1D,但没有行索引:

In [103]: A = a.to_numpy(); A
Out[103]: array([1, 3, 5, 7, 9], dtype=int64)

应用一行b为以下各项编制索引:

In [104]: A[b[0]]
Out[104]: array([3, 7], dtype=int64)

并对所有行反复执行此操作:

In [105]: [A[row] for row in b]
Out[105]: [array([3, 7], dtype=int64), array([], dtype=int64)]

我们可以从A生成一个(2,5)数组,然后应用b布尔掩码-但结果将是1D,没有任何迹象表明第二行没有选择任何内容:

In [106]: np.vstack((A,A))
Out[106]: 
array([[1, 3, 5, 7, 9],
       [1, 3, 5, 7, 9]], dtype=int64)

In [107]: np.vstack((A,A))[b]
Out[107]: array([3, 7], dtype=int64)

使用一行bb本身进行索引就是我所说的“完整数组”操作。但是不能单独使用b的行;它需要进行一次Python级别的迭代。
使用Ab还有其他一些方法:
乘法起作用,其中b被视为0和1的数组:

In [111]: A*b
Out[111]: 
array([[0, 3, 0, 7, 0],
       [0, 0, 0, 0, 0]], dtype=int64)

还有一个masked array子类的数组:

In [112]: np.ma.masked_array(np.vstack((A,A)),~b)
Out[112]: 
masked_array(
  data=[[--, 3, --, 7, --],
        [--, --, --, --, --]],
  mask=[[ True, False,  True, False,  True],
        [ True,  True,  True,  True,  True]],
  fill_value=999999,
  dtype=int64)

[105]数组列表可以转换为object dtype数组:

In [115]: np.array([A[row] for row in b],object)
Out[115]: array([array([3, 7], dtype=int64), array([], dtype=int64)], dtype=object)

这是1D,形状为(2,)。有时它是有用的,但在性能方面它并不是对列表的改进。

wqnecbli

wqnecbli2#

您可以简单地使用:

a2 = a.to_numpy()
out = [a2[x] for x in b]

输出:[array([3, 7]), array([], dtype=int64)]

kxe2p93d

kxe2p93d3#

或者,只需使用数组b作为掩码,例如:

out = a[b[0]].to_numpy()

相关问题