numpy - return 索引如果值在 3d 数组之一内
numpy - return index If value inside one of 3d array
如何在 Numpy 中执行此操作:谢谢!
输入:
A = np.array([0, 1, 2, 3])
B = np.array([[3, 2, 0], [0, 2, 1], [2, 3, 1], [3, 0, 1]])
输出:
result = [[0, 1, 3], [1, 2, 3], [0, 1, 2], [0, 2, 3]]
在 Python 中:
A = np.array([0 ,1 ,2 ,3])
B = np.array([[3 ,2 ,0], [0 ,2 ,1], [2 ,3 ,1], [3 ,0 ,1]])
result = []
for x , valA in enumerate (A) :
inArray = []
for y , valB in enumerate (B) :
if valA in valB:
inArray.append (y)
result.append (inArray)
print result
# result = [[0, 1, 3], [1, 2, 3], [0, 1, 2], [0, 2, 3]]
方法 #1
这是一个使用 broadcasting
-
的 NumPy 向量化方法
R,C = np.where((A[:,None,None] == B).any(-1))
out = np.split(C,np.flatnonzero(R[1:]>R[:-1])+1)
方法 #2
假设 A
和 B
保持正数,我们可以认为它们代表 2D
网格上的索引,这样 B
可以被认为保持每行的列索引。一旦对应于 B
的 2D
网格就位,我们只需要考虑与 A
相交的列。最后,我们在这样的 2D
网格中获得 True
值的索引,从而为我们提供 R
和 C
值。这应该更节省内存。
因此,替代方法看起来像这样 -
ncols = B.max()+1
nrows = B.shape[0]
mask = np.zeros((nrows,ncols),dtype=bool)
mask[np.arange(nrows)[:,None],B] = 1
mask[:,~np.in1d(np.arange(mask.shape[1]),A)] = 0
R,C = np.where(mask.T)
out = np.split(C,np.flatnonzero(R[1:]>R[:-1])+1)
样本运行-
In [43]: A
Out[43]: array([0, 1, 2, 3])
In [44]: B
Out[44]:
array([[3, 2, 0],
[0, 2, 1],
[2, 3, 1],
[3, 0, 1]])
In [45]: out
Out[45]: [array([0, 1, 3]), array([1, 2, 3]), array([0, 1, 2]), array([0, 2, 3])]
运行时测试
将数据集大小扩大 100x
,这是一个快速 运行 时间测试结果 -
In [85]: def index_1din2d(A,B):
...: R,C = np.where((A[:,None,None] == B).any(-1))
...: out = np.split(C,np.flatnonzero(R[1:]>R[:-1])+1)
...: return out
...:
...: def index_1din2d_initbased(A,B):
...: ncols = B.max()+1
...: nrows = B.shape[0]
...: mask = np.zeros((nrows,ncols),dtype=bool)
...: mask[np.arange(nrows)[:,None],B] = 1
...: mask[:,~np.in1d(np.arange(mask.shape[1]),A)] = 0
...: R,C = np.where(mask.T)
...: out = np.split(C,np.flatnonzero(R[1:]>R[:-1])+1)
...: return out
...:
In [86]: A = np.unique(np.random.randint(0,10000,(400)))
...: B = np.random.randint(0,10000,(400,300))
...:
In [87]: %timeit [np.where((B == x).sum(axis = 1))[0] for x in A]
1 loop, best of 3: 161 ms per loop # @Psidom's soln
In [88]: %timeit index_1din2d(A,B)
10 loops, best of 3: 91.5 ms per loop
In [89]: %timeit index_1din2d_initbased(A,B)
10 loops, best of 3: 33.4 ms per loop
性能进一步提升!
嗯,或者我们可以在第二种方法中以转置的方式创建 2D
网格。这个想法是为了避免 R,C = np.where(mask.T)
中的转置,这似乎是瓶颈。因此,第二种方法的修改版本和相关的 运行 时间看起来像这样 -
In [135]: def index_1din2d_initbased_v2(A,B):
...: nrows = B.max()+1
...: ncols = B.shape[0]
...: mask = np.zeros((nrows,ncols),dtype=bool)
...: mask[B,np.arange(ncols)[:,None]] = 1
...: mask[~np.in1d(np.arange(mask.shape[0]),A)] = 0
...: R,C = np.where(mask)
...: out = np.split(C,np.flatnonzero(R[1:]>R[:-1])+1)
...: return out
...:
In [136]: A = np.unique(np.random.randint(0,10000,(400)))
...: B = np.random.randint(0,10000,(400,300))
...:
In [137]: %timeit index_1din2d_initbased(A,B)
10 loops, best of 3: 57.5 ms per loop
In [138]: %timeit index_1din2d_initbased_v2(A,B)
10 loops, best of 3: 25.9 ms per loop
具有numpy
和list-comprehension
组合的选项:
import numpy as np
[np.where((B == x).sum(axis = 1))[0] for x in A]
# [array([0, 1, 3]), array([1, 2, 3]), array([0, 1, 2]), array([0, 2, 3])]
如何在 Numpy 中执行此操作:谢谢!
输入:
A = np.array([0, 1, 2, 3])
B = np.array([[3, 2, 0], [0, 2, 1], [2, 3, 1], [3, 0, 1]])
输出:
result = [[0, 1, 3], [1, 2, 3], [0, 1, 2], [0, 2, 3]]
在 Python 中:
A = np.array([0 ,1 ,2 ,3])
B = np.array([[3 ,2 ,0], [0 ,2 ,1], [2 ,3 ,1], [3 ,0 ,1]])
result = []
for x , valA in enumerate (A) :
inArray = []
for y , valB in enumerate (B) :
if valA in valB:
inArray.append (y)
result.append (inArray)
print result
# result = [[0, 1, 3], [1, 2, 3], [0, 1, 2], [0, 2, 3]]
方法 #1
这是一个使用 broadcasting
-
R,C = np.where((A[:,None,None] == B).any(-1))
out = np.split(C,np.flatnonzero(R[1:]>R[:-1])+1)
方法 #2
假设 A
和 B
保持正数,我们可以认为它们代表 2D
网格上的索引,这样 B
可以被认为保持每行的列索引。一旦对应于 B
的 2D
网格就位,我们只需要考虑与 A
相交的列。最后,我们在这样的 2D
网格中获得 True
值的索引,从而为我们提供 R
和 C
值。这应该更节省内存。
因此,替代方法看起来像这样 -
ncols = B.max()+1
nrows = B.shape[0]
mask = np.zeros((nrows,ncols),dtype=bool)
mask[np.arange(nrows)[:,None],B] = 1
mask[:,~np.in1d(np.arange(mask.shape[1]),A)] = 0
R,C = np.where(mask.T)
out = np.split(C,np.flatnonzero(R[1:]>R[:-1])+1)
样本运行-
In [43]: A
Out[43]: array([0, 1, 2, 3])
In [44]: B
Out[44]:
array([[3, 2, 0],
[0, 2, 1],
[2, 3, 1],
[3, 0, 1]])
In [45]: out
Out[45]: [array([0, 1, 3]), array([1, 2, 3]), array([0, 1, 2]), array([0, 2, 3])]
运行时测试
将数据集大小扩大 100x
,这是一个快速 运行 时间测试结果 -
In [85]: def index_1din2d(A,B):
...: R,C = np.where((A[:,None,None] == B).any(-1))
...: out = np.split(C,np.flatnonzero(R[1:]>R[:-1])+1)
...: return out
...:
...: def index_1din2d_initbased(A,B):
...: ncols = B.max()+1
...: nrows = B.shape[0]
...: mask = np.zeros((nrows,ncols),dtype=bool)
...: mask[np.arange(nrows)[:,None],B] = 1
...: mask[:,~np.in1d(np.arange(mask.shape[1]),A)] = 0
...: R,C = np.where(mask.T)
...: out = np.split(C,np.flatnonzero(R[1:]>R[:-1])+1)
...: return out
...:
In [86]: A = np.unique(np.random.randint(0,10000,(400)))
...: B = np.random.randint(0,10000,(400,300))
...:
In [87]: %timeit [np.where((B == x).sum(axis = 1))[0] for x in A]
1 loop, best of 3: 161 ms per loop # @Psidom's soln
In [88]: %timeit index_1din2d(A,B)
10 loops, best of 3: 91.5 ms per loop
In [89]: %timeit index_1din2d_initbased(A,B)
10 loops, best of 3: 33.4 ms per loop
性能进一步提升!
嗯,或者我们可以在第二种方法中以转置的方式创建 2D
网格。这个想法是为了避免 R,C = np.where(mask.T)
中的转置,这似乎是瓶颈。因此,第二种方法的修改版本和相关的 运行 时间看起来像这样 -
In [135]: def index_1din2d_initbased_v2(A,B):
...: nrows = B.max()+1
...: ncols = B.shape[0]
...: mask = np.zeros((nrows,ncols),dtype=bool)
...: mask[B,np.arange(ncols)[:,None]] = 1
...: mask[~np.in1d(np.arange(mask.shape[0]),A)] = 0
...: R,C = np.where(mask)
...: out = np.split(C,np.flatnonzero(R[1:]>R[:-1])+1)
...: return out
...:
In [136]: A = np.unique(np.random.randint(0,10000,(400)))
...: B = np.random.randint(0,10000,(400,300))
...:
In [137]: %timeit index_1din2d_initbased(A,B)
10 loops, best of 3: 57.5 ms per loop
In [138]: %timeit index_1din2d_initbased_v2(A,B)
10 loops, best of 3: 25.9 ms per loop
具有numpy
和list-comprehension
组合的选项:
import numpy as np
[np.where((B == x).sum(axis = 1))[0] for x in A]
# [array([0, 1, 3]), array([1, 2, 3]), array([0, 1, 2]), array([0, 2, 3])]