如果我有一个numpy.ndarray,比如300个点(现在是1 x 300),我想每30分选择10个点,我该怎么做?
换句话说:我想要前10个点,然后跳过20个,然后再抓10个,然后跳过10个......直到数组结束.
要从10每个元素块中选择元素30,我们可以简单地2D将10每行的第一列重新整形并切出-
a.reshape(-1,30)[:,:10]
Run Code Online (Sandbox Code Playgroud)
好处是输出将是输入的视图,因此几乎免费且没有任何额外的内存开销。让我们运行一个示例来展示和证明这些 -
In [43]: np.random.seed(0)
In [44]: a = np.random.randint(0,9,(1,300))
In [48]: np.shares_memory(a,a.reshape(10,30)[0,:,:10])
Out[48]: True
Run Code Online (Sandbox Code Playgroud)
如果您需要扁平版本,请使用.ravel()-
a.reshape(-1,30)[:,:10].ravel()
Run Code Online (Sandbox Code Playgroud)
时间——
In [38]: a = np.random.randint(0,9,(300))
# @sacul's soln
In [39]: %%timeit
...: msk = [True] * 10 + [False] * 20
...: out = a[np.tile(msk, len(a)//len(msk))]
100000 loops, best of 3: 7.6 µs per loop
# From this post
In [40]: %timeit a.reshape(-1,30)[:,:10].ravel()
1000000 loops, best of 3: 1.07 µs per loop
In [41]: a = np.random.randint(0,9,(3000000))
# @sacul's soln
In [42]: %%timeit
...: msk = [True] * 10 + [False] * 20
...: out = a[np.tile(msk, len(a)//len(msk))]
100 loops, best of 3: 3.66 ms per loop
# From this post
In [43]: %timeit a.reshape(-1,30)[:,:10].ravel()
100 loops, best of 3: 2.32 ms per loop
# If you are okay with `2D` output, it is virtually free
In [44]: %timeit a.reshape(-1,30)[:,:10]
1000000 loops, best of 3: 519 ns per loop
Run Code Online (Sandbox Code Playgroud)
1D数组的通用案例A. 元素数量是块长度的倍数
对于元素数是 的倍数的1D数组a,要从每个元素块中n选择元素并获得数组输出,我们将有:mn1D
a.reshape(-1,n)[:,:m].ravel()
Run Code Online (Sandbox Code Playgroud)
请注意,展ravel()平部分会在那里复制。所以,如果可能的话,2D为了内存效率,保留未扁平化的版本。
样品运行 -
In [59]: m,n = 2,5
In [60]: N = 25
In [61]: a = np.random.randint(0,9,(N))
In [62]: a
Out[62]:
array([5, 0, 3, 3, 7, 3, 5, 2, 4, 7, 6, 8, 8, 1, 6, 7, 7, 8, 1, 5, 8, 4,
3, 0, 3])
# Select 2 elements off each block of 5 elements
In [63]: a.reshape(-1,n)[:,:m].ravel()
Out[63]: array([5, 0, 3, 5, 6, 8, 7, 7, 8, 4])
Run Code Online (Sandbox Code Playgroud)
B. 通用编号 元素的
我们将利用np.lib.stride_tricks.as_strided, 灵感来自从每个元素块中this post选择元素 -mn
def skipped_view(a, m, n):
s = a.strides[0]
strided = np.lib.stride_tricks.as_strided
shp = ((a.size+n-1)//n,n)
return strided(a,shape=shp,strides=(n*s,s), writeable=False)[:,:m]
def slice_m_everyn(a, m, n):
a_slice2D = skipped_view(a,m,n)
extra = min(m,len(a)-n*(len(a)//n))
L = m*(len(a)//n) + extra
return a_slice2D.ravel()[:L]
Run Code Online (Sandbox Code Playgroud)
请注意,这skipped_view让我们可以查看输入数组,并可能查看未分配给输入数组的内存区域,但之后我们将展平和切片以将其限制为我们想要的输出,这就是一个副本。
样品运行 -
In [170]: np.random.seed(0)
...: a = np.random.randint(0,9,(16))
In [171]: a
Out[171]: array([5, 0, 3, 3, 7, 3, 5, 2, 4, 7, 6, 8, 8, 1, 6, 7])
# Select 2 elements off each block of 5 elements
In [172]: slice_m_everyn(a, m=2, n=5)
Out[172]: array([5, 0, 3, 5, 6, 8, 7])
In [173]: np.random.seed(0)
...: a = np.random.randint(0,9,(19))
In [174]: a
Out[174]: array([5, 0, 3, 3, 7, 3, 5, 2, 4, 7, 6, 8, 8, 1, 6, 7, 7, 8, 1])
# Select 2 elements off each block of 5 elements
In [175]: slice_m_everyn(a, m=2, n=5)
Out[175]: array([5, 0, 3, 5, 6, 8, 7, 7])
Run Code Online (Sandbox Code Playgroud)
您可以创建一个掩码并通过掩码创建索引,重复直到达到数组的长度:
msk = [True] * 10 + [False] * 20
arr[np.tile(msk, len(arr)//len(msk))]
Run Code Online (Sandbox Code Playgroud)
最小的例子:
在包含 30 个值的数组中,选择 1 个元素,然后跳过 2 个元素:
>>> arr
array([6, 7, 2, 7, 1, 9, 1, 4, 4, 8, 6, 5, 2, 6, 3, 6, 8, 5, 6, 7, 2, 1, 9,
6, 7, 2, 1, 8, 2, 2])
msk = [True] * 1 + [False] * 2
>>> arr[np.tile(msk, len(arr)//len(msk))]
array([6, 7, 1, 8, 2, 6, 6, 1, 7, 8])
Run Code Online (Sandbox Code Playgroud)
解释:
msk是一个布尔掩码
>>> msk
[True, False, False]
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用 重复该掩码np.tile,直到它与原始数组的长度相同(即数组的长度除以掩码的长度):
>>> np.tile(msk, len(arr)//len(msk))
array([ True, False, False, True, False, False, True, False, False,
True, False, False, True, False, False, True, False, False,
True, False, False, True, False, False, True, False, False,
True, False, False], dtype=bool)
Run Code Online (Sandbox Code Playgroud)
然后就是通过布尔值进行索引的简单问题,它numpy擅长
| 归档时间: |
|
| 查看次数: |
151 次 |
| 最近记录: |