我喜欢我的对象紧凑地打印出来(不需要加载),因此numpy.array被打印为常规元组(在本例中)。相反,我看到一条错误消息TypeError: data type not understood
。
知道导致错误消息的原因和(一旦解决)如何
class A:
def __init__(self):
from numpy import array
self.a_array = array([1,2,3])
def __repr__(self):
from yaml import dump
return dump(self, default_flow_style=False)
A()
所需的输出类似于:
object:A
a_array:
- 1, 2, 3
有什么想法吗?
更新:这可能有效(如果可实现):有没有办法让yaml表示器将任何array
变量x
替换为x.tolist()
表示?
答案 0 :(得分:3)
您是否有兴趣生成有效的yaml
,或仅使用yaml
作为展示对象的方式?需要没有负载的短语'建议后者。
但为什么要专注于yaml
?它是否以您想要的方式本地处理列表或序列?
如果我使用tolist
将数组转换为yaml
可以转储的列表,我会得到:
In [130]: a = np.arange(3)
In [131]: print(yaml.dump({'a':a.tolist()},default_flow_style=False))
a:
- 0
- 1
- 2
In [132]: print(yaml.dump({'a':a.tolist()},default_flow_style=True))
{a: [0, 1, 2]}
我可以删掉字典部分。但无论哪种方式,列表部分都不会显示为:
- 1, 2, 3
我不知道yaml.dump
对默认数组显示有何改进:
In [133]: print(a)
[0 1 2]
In [134]: print(repr(a))
array([0, 1, 2])
对于2D阵列(以及可以转换为2d的阵列),np.savetxt
提供紧凑的显示,并使用fmt
选项来控制细节:
In [139]: np.savetxt('test',a[None,:], fmt='%d')
In [140]: cat 'test'
0 1 2
这里我实际上写了一个文件,并用系统cat
显示,但我也可以写入字符串缓冲区。
但我可以做得更好。 savetxt
只是将数组一次一行写入文件。我可以直接使用相同的格式样式。
我为fmt
(此处为1d数组)中的每个项目创建了一个%
字符串,其a
规范。然后fmt%tuple(...)
格式化它。这只是直接的Python字符串格式化。
In [144]: fmt = ', '.join(['%d']*a.shape[0])
In [145]: fmt
Out[145]: '%d, %d, %d'
In [146]: fmt%tuple(a.tolist())
Out[146]: '0, 1, 2'
我可以为该格式添加-
和缩进,冒号等。
================================
import numpy as np
class A:
def __init__(self, anArray):
self.a_array = anArray
def __repr__(self):
astr = ['object: %s'%self.__class__]
astr.append('a_array:')
astr.append(self.repr_array())
return '\n'.join(astr)
def repr_array(self):
a = self.a_array
if a.ndim==1:
a = a[None,:]
fmt = ', '.join(['%d']*a.shape[1])
fmt = '- '+fmt
astr = []
for row in a:
astr.append(fmt%tuple(row))
astr = '\n'.join(astr)
return astr
print A(np.arange(3))
print A(np.ones((3,2)))
生成
object: __main__.A
a_array:
- 0, 1, 2
表示1d数组,
object: __main__.A
a_array:
- 1, 1
- 1, 1
- 1, 1
表示2d数组。
=======================================
import yaml
def numpy_representer_str(dumper, data):
# first cut ndarray yaml representer
astr = ', '.join(['%s']*data.shape[0])%tuple(data)
return dumper.represent_scalar('!ndarray:', astr)
def numpy_representer_seq(dumper, data):
return dumper.represent_sequence('!ndarray:', data.tolist())
yaml.add_representer(np.ndarray, numpy_representer_str)
print (yaml.dump({'a':np.arange(4)},default_flow_style=False))
yaml.add_representer(np.ndarray, numpy_representer_seq)
print (yaml.dump({'a':np.arange(4)},default_flow_style=False))
class A:
def __init__(self, anArray):
self.a_array = anArray
def __repr__(self):
astr = ['object: %s'%self.__class__]
astr.append('a_array:')
astr.append(self.repr_array())
return '\n'.join(astr)
def repr_array(self):
return yaml.dump(self.a_array)
print (A(np.arange(3)))
print (A(np.arange(6).reshape(2,3)))
对于不同风格的numpy代表,我得到的印象如下:
a: !ndarray: '0, 1, 2, 3' # the string version
a: !ndarray: # the sequence version
- 0
- 1
- 2
- 3
object: <class '__main__.A'> # sequence version with 1d
a_array:
!ndarray: [0, 1, 2]
object: <class '__main__.A'> # sequence version with 2d
a_array:
!ndarray:
- [0, 1, 2]
- [3, 4, 5]
答案 1 :(得分:1)
在A对象中表示时,可以将numpy数组封送到列表中。然后在从对象中检索时解组它:
class A:
def __init__(self):
from numpy import array
self.a_lst = [1,2,3]
def __repr__(self):
from yaml import dump
return dump(self, default_flow_style=False)
# convert internal list to numpy array before returning.
@property
def my_arr(self):
return array(self.a_lst)
# convert array to list before storing internally.
@my_arr.setter
def my_arr(self, array):
self.a_lst = array.tolist()
print(repr(A()))
关键是要确保在对象内部将数组存储为普通的python列表,这样就可以确保可以进行yaml转储。
可能更好的选择是使用numpy提供的内置dump
功能。请参阅answer here。