如何在numpy中获得dtype的步幅?

时间:2015-09-30 17:57:13

标签: python numpy stride

我想我可以这样做:np.zeros((), dtype=dt).strides,但是当dtype是一个大型数组类型时,这似乎并不高效:('<f8', (200, 100))。有没有办法直接从dtype直接进入numpy?

2 个答案:

答案 0 :(得分:3)

实际上,您可以在结构化数组中获得子数组的步幅,而无需创建&#34; full&#34;阵列。

结构化数组中的子数组必须是连续的并且在C-order according to the documentation中。请注意第一个例子上方的句子:

  

子数组始终具有C连续的内存布局。

因此,对于没有字段的结构化数组,例如示例中的字段,您可以(作为不可读的单行):

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demoApp">
    <my-dir></my-dir>
</div>

避免代码高尔夫:

import numpy as np

x = np.dtype(('<f8', (200, 100)))

strides = x.base.itemsize * np.r_[1, np.cumprod(x.shape[::-1][:-1])][::-1]

但是,当存在多个字段时,这会变得更加复杂。一般来说,您需要进行适当的检查。例如:dtype是否具有shape = list(x.shape) # First, let's make the strides for an array with an itemsize of 1 in C-order tmp_strides = shape[::-1] tmp_strides[1:] = list(np.cumprod(tmp_strides[:-1])) tmp_strides[0] = 1 # Now adjust it for the real itemsize: tmp_strides = x.base.itemsize * np.array(tmp_strides) # And convert it to a tuple, reversing it back for proper C-order strides = tuple(tmp_strides[::-1]) 属性?它有田地吗?任何字段都有shape个属性吗?

答案 1 :(得分:2)

我认为你在谈论一个阵列:

In [257]: dt=np.dtype([('f0',float, (200,100))])
In [258]: x=np.zeros((),dtype=dt)

数组本身是0d,只有一个项目。

In [259]: x.strides
Out[259]: ()

该项目的形状和步幅由dtype决定:

In [260]: x['f0'].strides
Out[260]: (800, 8)
In [261]: x['f0'].shape
Out[261]: (200, 100)

但是构造x与构造具有相同形状的普通浮点数不同吗?

In [262]: y=np.zeros((200,100),float)
In [263]: y.strides
Out[263]: (800, 8)

在没有实际构建它的情况下,您无法获得潜在y的步伐。

Ipython whos命令显示xy占用相同的空间:

x          ndarray       : 1 elems, type `[('f0', '<f8', (200, 100))]`,
   160000 bytes (156.25 kb)
y          ndarray       200x100: 20000 elems, type `float64`, 
   160000 bytes (156.25 kb)

一个棘手的问题是这样的x['f0']是否具有y的所有属性。您可以阅读所有属性,但可能会限制您可以更改的属性。

您可以解析dtype:

In [309]: dt=np.dtype([('f0',float, (200,100))])
In [310]: dt.fields
Out[310]: mappingproxy({'f0': (dtype(('<f8', (200, 100))), 0)})
In [311]: dt[0]
Out[311]: dtype(('<f8', (200, 100)))
In [312]: dt[0].shape
Out[312]: (200, 100)
In [324]: dt[0].base
Out[324]: dtype('float64')

我没有看到stridesdt的{​​{1}}类似属性。可能有一些dt[0]函数根据numpy计算strides,但它可能是隐藏的。您可以搜索shape模块。找到np.lib.stride_tricks的地方。

as_strided形状和(200,100)取8个字节,可以计算出正常(默认)步幅为float64

对于没有进一步嵌套的dtype,这似乎有效:

(8*100, 8)

让我们用这个dtype

制作一个更复杂的数组
In [374]: dt[0]
Out[374]: dtype(('<f8', (200, 100)))
In [375]: tuple(np.array(dt[0].shape[1:]+(1,))*dt[0].base.itemsize)
Out[375]: (800, 8)

它的步幅取决于形状和In [346]: x=np.zeros((3,1),dtype=dt) In [347]: x.shape Out[347]: (3, 1) In [348]: x.strides Out[348]: (160000, 160000) 。但是场地的形状和步幅是4d。我们可以说他们存在而没有真正进入该领域吗?

itemsize

大步前进:

In [349]: x['f0'].strides
Out[349]: (160000, 160000, 800, 8)

双重嵌套怎么样?

In [350]: x[0,0]['f0'].strides
Out[350]: (800, 8)

校正,对于场地的跨越是整个阵列的跨越加上对场的跨越的组合。可以看到多字段dtype

In [390]: dt1=np.dtype([('f0',np.dtype([('f00',int,(3,4))]), (20,10))])
In [391]: z=np.zeros((),dt1)
In [392]: z['f0']['f00'].shape
Out[392]: (20, 10, 3, 4)
In [393]: z['f0']['f00'].strides
Out[393]: (480, 48, 16, 4)
In [399]: (np.cumprod(np.array((10,3,4,1))[::-1])*4)[::-1]
Out[399]: array([480,  48,  16,   4], dtype=int32)

In [430]: dt=np.dtype([('f0',float, (3,4)),('f1',int),('f2',int,(2,))]) In [431]: x=np.zeros((3,2),dt) In [432]: x.shape Out[432]: (3, 2) In [433]: x.strides Out[433]: (216, 108) In [434]: x['f0'].shape Out[434]: (3, 2, 3, 4) In [435]: x['f0'].strides Out[435]: (216, 108, 32, 8) 正在争取整个数组(itemsize为108),与(216,108)字段f0(itemsize 8)的跨越相连接。