Numpy子集矩阵基于另一个二进制数据

时间:2017-02-06 16:26:41

标签: python numpy

我有n x m矩阵Xn x p矩阵Y,其中Y是二进制数据。最后,我想要一个p x n矩阵Z,其中Z的列是X列的列的函数,这些列对应于1' s的列条目在Y

例如

>>> X
array([[1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]])
>>> Y
array([[1, 0],
    [1, 0],
    [0, 1]])
n_x,m = X.shape
n_y,p = Y.shape
Z = np.zeros([p, n_x])
for i in range(n_x):
    col = X[:,[i]]
    for j in range(p):
        #this is where I subset col with Y[:,[j]]
        Z[j][i] = my_func(subsetted_column)

迭代会产生

i=0, j=0: subsetted_column = [[1],[4]]
i=0, j=1: subsetted_column = [[7]]
i=1, j=0: subsetted_column = [[2],[5]]
i=1, j=1: subsetted_column = [[8]]
i=2, j=0: subsetted_column = [[3],[6]]
i=2, j=1: subsetted_column = [[9]]

我假设有一些方法可以在单个列表推导中执行嵌套循环。函数my_func也需要很长时间,所以以某种方式并行化很好。

修改:我可以做类似

的事情
for i in range(n_x):
    for j in range(p):
        subsetted_column = np.trim_zeros(np.multiply(X[:,i], Y[:,j]))
        Z[j][i] = my_func(subsetted_column)

但我仍然相信有一个更简单的解决方案

2 个答案:

答案 0 :(得分:2)

这是你想要的吗?

import numpy as np

N, M, P = 4, 3, 2

a = np.random.random((N, M))
b = np.random.randint(2, size=(N, P)).astype(bool)

your_func = lambda x: x # insert proper function here
flat = [your_func(ai[bj]) for bj in b.T for ai in a.T]

out = np.empty((P, M), dtype=object)
out.ravel()[:] = flat
print(a)
print(b)
print(out)

说明:

  • 最简单的方法是将屏蔽数组转换为dtype bool,因为这样可以使用逻辑索引。
  • 如果your_func只返回一个数字,最好不要dtype=object使用out
  • 如果你想并行化,列表理解可能不是最好的事情,但我不是那么专家。只是循环看起来像一个明显的并行化目标,因为迭代的顺序是无关紧要的。

示例输出:

[[ 0.62739382  0.85774837  0.81958524]
 [ 0.99690996  0.71202879  0.97636715]
 [ 0.89235107  0.91739852  0.39537849]
 [ 0.0413107   0.11662271  0.72419308]]
[[False  True]
 [ True  True]
 [False False]
 [ True  True]]
[[array([ 0.99690996,  0.0413107 ]) array([ 0.71202879,  0.11662271])
  array([ 0.97636715,  0.72419308])]
 [array([ 0.62739382,  0.99690996,  0.0413107 ])
  array([ 0.85774837,  0.71202879,  0.11662271])
  array([ 0.81958524,  0.97636715,  0.72419308])]]

答案 1 :(得分:0)

在预处理循环中执行子集可能会有所帮助

In [112]: xs = [X[y,:] for y in Y.astype(bool).T]
In [113]: xs
Out[113]: 
[array([[1, 2, 3],
        [4, 5, 6]]), 
 array([[7, 8, 9]])]

.T用于迭代列表推导中的列; bool允许'蒙面'选择)

比方说,例如,my_func取轴上的均值= 0为子集

In [116]: [np.mean(s, axis=0) for s in xs]
Out[116]: [array([ 2.5,  3.5,  4.5]), array([ 7.,  8.,  9.])]
In [117]: np.array(_)
Out[117]: 
array([[ 2.5,  3.5,  4.5],
       [ 7. ,  8. ,  9. ]])

我可以把它组合成一个循环,但是更难想到:

np.array([np.mean(X[y,:],axis=0) for y in Y.astype(bool).T])

借助此xs列表,您可以集中精力将my_func有效地应用于xs[i] np.mean(xs[i], axis=0)的所有列。

这个双循环版本

In [121]: p=np.zeros((2,3))
In [122]: for i in range(2):
     ...:     for j in range(3):
     ...:         p[i,j] = np.mean(xs[i][:,j])
     ...:         
In [123]: p
Out[123]: 
array([[ 2.5,  3.5,  4.5],
       [ 7. ,  8. ,  9. ]])

等效双重列表理解

In [125]: [[np.mean(i) for i in j.T] for j in xs]
Out[125]: [[2.5, 3.5, 4.5], [7.0, 8.0, 9.0]]