我已经使用npy
在C ++程序中编写了一个cnpy
文件:
vector < double > vrmsd(max,99.9);
.
.
.
cnpy::npy_save(frmsd,&vrmsd,{nfeat},"w");
以示例here为例。
但是当我尝试使用numpy
加载文件时,出现错误
y = np.load(frmsd)
ValueError: descr is not a valid dtype descriptor: '<?24'
下面,我将hexdump -C
的结果粘贴到一个npy
文件中,该文件包含一个长度为2的vector<double>
(应包含46.950、43.94):
00000000 93 4e 55 4d 50 59 01 00 46 00 7b 27 64 65 73 63 |.NUMPY..F.{'desc|
00000010 72 27 3a 20 27 3c 3f 32 34 27 2c 20 27 66 6f 72 |r': '<?24', 'for|
00000020 74 72 61 6e 5f 6f 72 64 65 72 27 3a 20 46 61 6c |tran_order': Fal|
00000030 73 65 2c 20 27 73 68 61 70 65 27 3a 20 28 32 2c |se, 'shape': (2,|
00000040 29 2c 20 7d 20 20 20 20 20 20 20 20 20 20 20 0a |), } .|
00000050 10 4d 1b 02 00 00 00 00 20 4d 1b 02 00 00 00 00 |.M...... M......|
00000060 20 4d 1b 02 00 00 00 00 00 ff 00 00 00 ff 00 00 | M..............|
00000070 c8 33 19 02 00 00 00 00 94 99 90 5b 00 00 00 00 |.3.........[....|
00000080
此问题也已发布到cnpy
github网站。只是想知道我在numpy
方面是否可以做些什么?谢谢。
答案 0 :(得分:0)
如果您想从numpy方面解决此问题……那么,您可能不想修改numpy以理解非标准的descr字符串,而且我怀疑即使您将该descr字符串视为似乎是正确的声称无论如何都会得到垃圾。
但是您可以进行一些变通的解决方法。
如果打开二进制文件,则应以以下内容开头:
\x93NUMPY\x01\x00v\x00{'descr': '<?24', 'fortran_order': False, 'shape': (30, 20), }
...,后跟一些空格,这些空格在原始字节之前以换行符结尾。
您可以在十六进制编辑器或文本编辑器中仔细编辑此文件,也可以使用Python代码以二进制模式打开文件,读取文件,对字节执行一些常规的字符串操作并写回。
特别是,看起来像python dict repr的位实际上就是那个,并且这些值恰好代表了您认为的含义。加载文件最终尝试创建np.dtype('<?24')
,这就是错误的出处。
如果您仅编辑descr
和shape
值,并确保将dict repr保持相同的长度(通过填充空格),那将为您提供一些{{1} }。
那么load
是什么意思?嗯,这不是PEP 3118和struct
指定的有效格式,但是它确实适合numpy对该格式的扩展名。例如,在numpy中,您可以指定<?24
,意思是“与f8
相同,但为8个字节”。因此,假设这意味着f
的24字节小尾数版本,如果使用C99编译则表示?
,如果不是,则表示_Bool
,并且应解释为{{ 1}}。
因此,如果numpy允许此descr指定dtype,则意味着每个单元格均为24字节,解释为小尾数整数,解释为bool。当然,numpy不知道如何处理除1、2、4或8个字节以外的任何长度的整数,并且它期望布尔值是1个字节,因此是不允许的。但是您可以读到与24个独立的bool相同的内容。
您如何做到的?只需将char
字符串更改为bool
,将descr
更改为'?'
,现在您将获得30x20x24布尔数组,并且如果对shape
进行切片,您将获得一个30x20的布尔数组。或者,(30, 20, 24)
可能会这样做而无需更改[..., 0]
。
问题是,您的C ++值为double,而不是布尔值。
希望它是用little-endian格式写的double,每个double后面有16个额外的0字节。如果是这样,只需将'24?'
更改为shape
,将descr
更改为'<f8'
,然后看看会得到什么。如果第一个shape
是您想要的数组,而其他两个都是零,那么您就完成了;切成薄片。 (如果您想减少内存使用量,可以使用(30, 20, 3)
。)
答案 1 :(得分:0)
在您提供的示例中,按照npy_save()
参数的格式存在错误。
而不是
cnpy::npy_save(frmsd,&vrmsd,{nfeat},"w");
您要
cnpy::npy_save(frmsd,&vrmsd[0],{nfeat},"w");