用np.savez存储一个dict会产生意想不到的结果吗?

lou*_*uic 12 python arrays dictionary numpy save

我可以使用np.savez存储字典吗?结果令人惊讶(至少对我来说),我找不到通过密钥获取数据的方法.

In [1]: a = {'0': {'A': array([1,2,3]), 'B': array([4,5,6])}}
In [2]: a
Out[2]: {'0': {'A': array([1, 2, 3]), 'B': array([4, 5, 6])}}

In [3]: np.savez('model.npz', **a)
In [4]: a = np.load('model.npz')
In [5]: a
Out[5]: <numpy.lib.npyio.NpzFile at 0x7fc9f8acaad0>

In [6]: a['0']
Out[6]: array({'B': array([4, 5, 6]), 'A': array([1, 2, 3])}, dtype=object)

In [7]: a['0']['B']
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-16-c916b98771c9> in <module>()
----> 1 a['0']['B']

ValueError: field named B not found

In [8]: dict(a['0'])
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-17-d06b11e8a048> in <module>()
----> 1 dict(a['0'])

TypeError: iteration over a 0-d array
Run Code Online (Sandbox Code Playgroud)

我不明白到底发生了什么.看来我的数据变成了一个0维数组中的字典,让我无法通过密钥获取数据.或者我错过了什么?

所以我的问题是:

  1. 这里发生了什么?如果我仍然可以通过密钥访问我的数据,怎么样?
  2. 存储此类数据的最佳方法是什么?(以str作为键和其他值作为值的词典)

谢谢!

unu*_*tbu 14

可以恢复数据:

In [41]: a = {'0': {'A': array([1,2,3]), 'B': array([4,5,6])}}

In [42]: np.savez('/tmp/model.npz', **a)

In [43]: a = np.load('/tmp/model.npz')
Run Code Online (Sandbox Code Playgroud)

请注意,dtype是'object'.

In [44]: a['0']
Out[44]: array({'A': array([1, 2, 3]), 'B': array([4, 5, 6])}, dtype=object)
Run Code Online (Sandbox Code Playgroud)

并且阵列中只有一个项目.那个项目是Python dict!

In [45]: a['0'].size
Out[45]: 1
Run Code Online (Sandbox Code Playgroud)

您可以检索使用值item()方法(注:这是不是该 items()对字典的方法,也没有什么内在的NpzFile 类,但它是 numpy.ndarray.item()方法 是数组中的值复制到一个标准的Python标量在数组.objectD型的任意值保存在数组的单元格中(甚至是字典)是一个Python标量:

In [46]: a['0'].item()
Out[46]: {'A': array([1, 2, 3]), 'B': array([4, 5, 6])}

In [47]: a['0'].item()['A']
Out[47]: array([1, 2, 3])

In [48]: a['0'].item()['B']
Out[48]: array([4, 5, 6])
Run Code Online (Sandbox Code Playgroud)

要恢复a为dicts的词典:

In [84]: a = np.load('/tmp/model.npz')

In [85]: a = {key:a[key].item() for key in a}

In [86]: a['0']['A']
Out[86]: array([1, 2, 3])
Run Code Online (Sandbox Code Playgroud)

  • @zhermes:如果你追踪[源代码](https://github.com/numpy/numpy/blob/v1.9.1/numpy/lib/npyio.py#L459),你会发现[`_savez`调用`np.asanyarray(val)`](https://github.com/numpy/numpy/blob/v1.9.1/numpy/lib/npyio.py#L597)所以,当val是一个字典时,`_savez`将其转换为数组.例如,`np.asanyarray({'a':'b'})`是`array({'a':'b'},dtype = object)`. (2认同)