[英]subsetting 2d numpy array and keeping rows consistent
我想知道执行以下操作的最简单方法是:
假设我们有以下二维数组:
>>> a = np.array([['z', 'z', 'z', 'f', 'z','f', 'f'], ['z', 'z', 'z', 'f', 'z','f', 'f']])
array([['z', 'z', 'z', 'f', 'z', 'f', 'f'],
['z', 'z', 'z', 'f', 'z', 'f', 'f']],
dtype='<U1')
>>> b = np.array(range(0,14)).reshape(2, -1)
array([[ 0, 1, 2, 3, 4, 5, 6],
[ 7, 8, 9, 10, 11, 12, 13]])
>>> idxs = list(zip(*np.where(a == 'f')))
[(0, 3), (0, 5), (0, 6), (1, 3), (1, 5), (1, 6)]
>>> [b[x] for x in idxs]
[3, 5, 6, 10, 12, 13]
但是,我想保留有关第一个索引或行的结构,即:
[[3, 5, 6], [7, 11]]
有没有一种方法可以轻松保持此结构?
使用for
循环:
[b[i][a[i] == 'f'] for i in range(len(a))]
# [array([3, 5, 6]), array([10, 12, 13])]
这是一个更复杂但纯粹的NumPy解决方案:
a
)它是一个'f'
。 代码如下所示:
>>> indices = np.flatnonzero(a.ravel() == 'f')
>>> rows = np.arange(1, a.shape[0])*a.shape[1]
>>> np.split(b.ravel()[indices], np.searchsorted(indices, rows))
[array([3, 5, 6], dtype=int64), array([10, 12, 13], dtype=int64)]
比其他解决方案长一点,我不确定是否会更快1 。
尽管就我个人而言,我会使用列表理解和zip
:
[b_row[a_row] for a_row, b_row in zip(a == 'f', b)]
它要短得多,并且根据我的时间安排,相当不错。
定时:
import numpy as np
a = np.array([['z', 'z', 'z', 'f', 'z','f', 'f']]*10000)
b = np.arange(a.size).reshape(-1, a.shape[1])
%%timeit
indices = np.flatnonzero(a.ravel() == 'f')
rows = np.arange(1, a.shape[0])*a.shape[1]
np.split(b.ravel()[indices], np.searchsorted(indices, rows))
每个循环123毫秒±8.25毫秒(平均±标准偏差,共7次运行,每个循环10次)
%timeit [b[i][a[i] == 'f'] for i in range(len(a))]
每个循环162 ms±14 ms(平均±标准偏差,共7次运行,每个循环1次)
但是,与我在Psidoms回答中的建议相比,速度要慢得多:
%timeit [b_row[a_row] for a_row, b_row in zip(a == 'f', b)]
每个循环44.9 ms±1.93 ms(平均±标准偏差,共运行7次,每个循环10个)
a = np.array([['z', 'z', 'z', 'f', 'z','f', 'f'], ['z', 'z', 'z', 'f', 'z','f', 'f']]) b = np.array(range(0,14)).reshape(2, -1) idxs = list(zip(*np.where(a == 'f'))) c=[[],[]] for x in idxs: c[x[0]].append(b[x]) print c
In [89]: idx = np.where(a == 'f')
In [90]: idx
Out[90]:
(array([0, 0, 0, 1, 1, 1], dtype=int32),
array([3, 5, 6, 3, 5, 6], dtype=int32))
我们可以应用where
元组在b
选择项目:
In [93]: b[idx]
Out[93]: array([ 3, 5, 6, 10, 12, 13])
等效地应用布尔掩码:
In [94]: b[a == 'f']
Out[94]: array([ 3, 5, 6, 10, 12, 13])
np.argwhere
进行where
的转置,产生一个2d数组,如idxs
。
In [95]: np.argwhere(a == 'f')
Out[95]:
array([[0, 3],
[0, 5],
[0, 6],
[1, 3],
[1, 5],
[1, 6]], dtype=int32)
如删除与布尔型遮罩相对应的数组中的所有元素中所述 ,通常,我们不能选择带有遮罩的元素并保留某种2d结构。 在某些情况下,我们可以将1d结果重塑为有意义的东西。
In [96]: b[idx].reshape(2,-1)
Out[96]:
array([[ 3, 5, 6],
[10, 12, 13]])
逐行收集这些值并允许每一行具有不同大小结果的一种简单方法是迭代:
In [100]: [j[i=='f'] for i,j in zip(a,b)]
Out[100]: [array([3, 5, 6]), array([10, 12, 13])]
In [101]: [j[i=='f'].tolist() for i,j in zip(a,b)]
Out[101]: [[3, 5, 6], [10, 12, 13]]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.