你有 2 个数组,一个是 2d 的数字,另一个是 1d 的字符串
In [53]: predictions = np.array([[0.2, 0.9], [0.01, 0.0], [0.3, 0.8]])
...: filenames = np.array(["file1", "file2", "file3"])
In [54]: predictions
Out[54]:
array([[ 0.2 , 0.9 ],
[ 0.01, 0. ],
[ 0.3 , 0.8 ]])
In [55]: filenames
Out[55]:
array(['file1', 'file2', 'file3'],
dtype='<U5')
如果您向filenames 添加一个维度(因此它变为 (3,1)),您可以将其与另一个维度连接 - 请注意轴。我使用的是 Py3,所以我的默认字符串类型是 unicode (U5)。
In [56]: arr = np.concatenate((filenames[:,None], predictions),axis=1)
In [57]: arr
Out[57]:
array([['file1', '0.2', '0.9'],
['file2', '0.01', '0.0'],
['file3', '0.3', '0.8']],
dtype='<U32')
请注意,结果是字符串类型。这可能没问题。 column_stack 和 vstack 也可以使用,但它们最终会像我一样调整尺寸并使用连接。
np.stack 在新维度上连接数组。我认为您不需要 3d 数组。
In [58]: np.savetxt('test', arr, fmt='%10s')
In [59]: cat test
file1 0.2 0.9
file2 0.01 0.0
file3 0.3 0.8
您可以调整fmt,但使用字符串时您会遇到%s 的一些变化。 savetxt 也允许页眉和页脚。
要对fmt 进行更多控制,例如小数位数等,我们必须构造一个结构化数组,将一个字符串字段与两个浮点字段混合在一起。如果需要,我可以对此进行扩展。
另一种选择是仅zip 数组并写入行。 savetxt 在编写文本文件时不会做任何神奇的事情。
In [65]: for f, n in zip(filenames, predictions):
...: print('%s %s'%(f, '%10.2f %10.2f'%tuple(n)))
...:
file1 0.20 0.90
file2 0.01 0.00
file3 0.30 0.80
鉴于从 1 列字符串和 2 列浮点数组创建结构化数组的复杂性,最后一种 zip 方法可能是最简单的。
结构化数组
In [114]: arr = np.zeros((3,),np.dtype('U10,f,f'))
In [115]: arr['f0']=filenames
In [116]: arr['f1']=predictions[:,0]
In [117]: arr['f2']=predictions[:,1]
In [118]: np.savetxt('test',arr, fmt='%10s %10.2f %10.1f')
In [119]: cat test
file1 0.20 0.9
file2 0.01 0.0
file3 0.30 0.8
构造这个数组的更简单的方法是:
arr = np.rec.fromarrays((filenames, predictions[:,0], predictions[:,1]))
我更喜欢制作这样的结构化数组:
In [123]: dt=np.dtype([('files', 'U10'), ('pred', 'float64', (2,))])
In [124]: dt
Out[124]: dtype([('files', '<U10'), ('pred', '<f8', (2,))])
In [125]: arr = np.zeros((3,),dtype=dt)
In [126]: arr['files']=filenames
In [127]: arr['pred']=predictions
In [128]: arr
Out[128]:
array([('file1', [0.2, 0.9]), ('file2', [0.01, 0.0]), ('file3', [0.3, 0.8])],
dtype=[('files', '<U10'), ('pred', '<f8', (2,))])
但 np.savetxt 无法处理该复合数据类型。所以我不得不求助于将预测放在不同的字段中。
pandas 在编写带有行标签的文件方面做得更好。