我有一个numpy数组,形状为(8000000, 7)
。
我希望将numpy数组的前6列保留为float32
数据类型,将最后一列保留为int8
类型。
最后,我想将其保存为csv文件。
我该如何管理?
答案 0 :(得分:2)
你可以构造一个结构化数组,但我想知道你是否需要,特别是如果你想要的只是一个csv文件。 fmt
参数控制savetxt
写入列的方式。
首先使用默认的fmt和column_stack
:
In [1484]: a=np.random.rand(5,3)
In [1485]: b=np.arange(5,dtype=np.int8)
In [1486]: np.savetxt('test.txt',np.column_stack((a,b)))
In [1487]: cat test.txt
3.513972543477327237e-01 8.468274950931957701e-01 6.587019305719005180e-01 0.000000000000000000e+00
...
使用更简单的浮动格式:
In [1492]: np.savetxt('test.txt',np.column_stack((a,b)),fmt='%f')
In [1493]: cat test.txt
0.351397 0.846827 0.658702 0.000000
0.566257 0.419570 0.183939 1.000000
0.276351 0.341277 0.706639 2.000000
0.515183 0.296801 0.321054 3.000000
0.305349 0.407097 0.328825 4.000000
或者通过指定每列的格式:
In [1496]: np.savetxt('test.txt',np.column_stack((a,b)),fmt=['%f']*3+['%d'])
In [1497]: cat test.txt
0.351397 0.846827 0.658702 0
0.566257 0.419570 0.183939 1
0.276351 0.341277 0.706639 2
0.515183 0.296801 0.321054 3
0.305349 0.407097 0.328825 4
==============================
使用这样的数据构造结构化数组的一个很好的方法是定义2个字段,并使第一个成为数组:
In [1503]: dt=np.dtype('(3)f,i8')
In [1504]: A=np.empty((5,),dtype=dt)
In [1505]: A['f0']=a
In [1506]: A['f1']=b
In [1507]: A
Out[1507]:
array([([0.35139724612236023, 0.846827507019043, 0.6587019562721252], 0),
([0.566256582736969, 0.41956955194473267, 0.18393920361995697], 1),
([0.27635079622268677, 0.3412773013114929, 0.706638514995575], 2),
([0.5151825547218323, 0.29680076241493225, 0.32105395197868347], 3),
([0.30534881353378296, 0.4070965051651001, 0.3288247585296631], 4)],
dtype=[('f0', '<f4', (3,)), ('f1', '<i8')])
不幸的是savetxt
无法处理那种'嵌套'dtype。我能做的最好的事情是将第一个字段格式化为字符串,使用[]
In [1509]: np.savetxt('test.txt',A,fmt=['%s','%d'])
In [1511]: cat test.txt
[ 0.35139725 0.84682751 0.65870196] 0
[ 0.56625658 0.41956955 0.1839392 ] 1
[ 0.2763508 0.3412773 0.70663851] 2
[ 0.51518255 0.29680076 0.32105395] 3
[ 0.30534881 0.40709651 0.32882476] 4
相反,我需要做一个扁平的dtype;我可以使用相同的字节布局将其应用于视图(或从头开始构造数组)
In [1512]: dt1=np.dtype('f,f,f,i8')
In [1514]: A.view(dt1)
Out[1514]:
array([(0.35139724612236023, 0.846827507019043, 0.6587019562721252, 0),
(0.566256582736969, 0.41956955194473267, 0.18393920361995697, 1),
(0.27635079622268677, 0.3412773013114929, 0.706638514995575, 2),
(0.5151825547218323, 0.29680076241493225, 0.32105395197868347, 3),
(0.30534881353378296, 0.4070965051651001, 0.3288247585296631, 4)],
dtype=[('f0', '<f4'), ('f1', '<f4'), ('f2', '<f4'), ('f3', '<i8')])
现在我可以用与之前相同的fmt
来编写它:
In [1515]: np.savetxt('test.txt',A.view(dt1),fmt=['%f']*3+['%d'])
In [1516]: cat test.txt
0.351397 0.846828 0.658702 0
0.566257 0.419570 0.183939 1
0.276351 0.341277 0.706639 2
0.515183 0.296801 0.321054 3
0.305349 0.407097 0.328825 4
如果您的一个或多个列是字符串,那么您将需要使用结构化数组。但只要所有列都是数字,您就可以使用全浮点数组,并使用fmt
控制打印。
答案 1 :(得分:1)
那么你可以构造dtype然后使用零或空来获得一个准备好数据的空shell。希望这会给你一些想法
>>> import numpy as np
>>>
>>> flds = ["f{:0>{}}".format(i,2) for i in range(7)]
>>> dt = [(fld, 'float32') for fld in flds]
>>> dt.append(('i01', 'int8'))
>>> a = np.zeros((10,), dtype=dt)
>>> a
array([(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0),
(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0),
(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0),
(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0),
(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0),
(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0),
(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0),
(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0),
(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0),
(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0)],
dtype=[('f00', '<f4'), ('f01', '<f4'), ('f02', '<f4'), ('f03', '<f4'), ('f04', '<f4'), ('f05', '<f4'), ('f06', '<f4'), ('i01', 'i1')])
>>>
使用此示例def
def num_45():
"""(num_45)...
"""
import numpy as np
flds = ["f{:0>{}}".format(i,2) for i in range(7)]
dt = [(fld, 'float32') for fld in flds]
dt.append(('i01', 'int8'))
a = np.zeros((10,), dtype=dt)
b = np.arange(10*8).reshape(10,8)
c = np.copy(a)
names = a.dtype.names
N = len(names)
for i in range(N):
c[names[i]] = b[:,i]
return a, b, c
结果
>>> a
array([(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0),
(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0),
(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0),
(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0),
(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0),
(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0),
(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0),
(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0),
(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0),
(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0)],
dtype=[('f00', '<f4'), ('f01', '<f4'), ('f02', '<f4'), ('f03', '<f4'), ('f04', '<f4'), ('f05', '<f4'), ('f06', '<f4'), ('i01', 'i1')])
>>> b
array([[ 0, 1, 2, 3, 4, 5, 6, 7],
[ 8, 9, 10, 11, 12, 13, 14, 15],
[16, 17, 18, 19, 20, 21, 22, 23],
[24, 25, 26, 27, 28, 29, 30, 31],
[32, 33, 34, 35, 36, 37, 38, 39],
[40, 41, 42, 43, 44, 45, 46, 47],
[48, 49, 50, 51, 52, 53, 54, 55],
[56, 57, 58, 59, 60, 61, 62, 63],
[64, 65, 66, 67, 68, 69, 70, 71],
[72, 73, 74, 75, 76, 77, 78, 79]])
>>> c
array([(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7),
(8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15),
(16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23),
(24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31),
(32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39),
(40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47),
(48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55),
(56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63),
(64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71),
(72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79)],
dtype=[('f00', '<f4'), ('f01', '<f4'), ('f02', '<f4'), ('f03', '<f4'), ('f04', '<f4'), ('f05', '<f4'), ('f06', '<f4'), ('i01', 'i1')])
用几行手动代码查看构造的另一个例子
n = ['It', 'is', 'easy']
dt = [(n[0], '<f8'), (n[1], '<i8'), (n[2], 'U5')]
d = np.zeros((10,), dtype=dt)
for i in range(len(n)):
d[n[i]] = b[:, i]
产量
>>> d.dtype.names
('It', 'is', 'easy')
>>> d.reshape(10,-1)
array([[(0.0, 1, '2')],
[(8.0, 9, '10')],
[(16.0, 17, '18')],
[(24.0, 25, '26')],
[(32.0, 33, '34')],
[(40.0, 41, '42')],
[(48.0, 49, '50')],
[(56.0, 57, '58')],
[(64.0, 65, '66')],
[(72.0, 73, '74')]],
dtype=[('It', '<f8'), ('is', '<i8'), ('easy', '<U5')])
答案 2 :(得分:1)
我认为将数组分解为浮点数和整数然后使用zip
和np.savetxt
的组合将它们全部重新组合在csv中会相对容易。但是Support zip input in savetxt in Python 3表明这种方式是疯狂的。
然而,由于坚持zip
想法,我只是将工作转移到标准csv
模块。由于numpy数据需要转换为python类型,因此可能会慢一些。但我们正在谈论csv
在这里写作,所以希望它只是在噪音中迷失了。
首先,生成测试数组
>>> import numpy as np
>>> array = np.arange(0., 18.*5, 5., dtype=np.float32).reshape((3,6))
>>> array
array([[ 0., 5., 10., 15., 20., 25.],
[ 30., 35., 40., 45., 50., 55.],
[ 60., 65., 70., 75., 80., 85.]], dtype=float32)
拆分最后一列并重铸为uint8
>>> floats, ints, _after = np.hsplit(array, (5,6))
>>> ints=ints.astype(np.uint8)
>>> floats
array([[ 0., 5., 10., 15., 20.],
[ 30., 35., 40., 45., 50.],
[ 60., 65., 70., 75., 80.]], dtype=float32)
>>> ints
array([[25],
[55],
[85]], dtype=uint8)
使用python csv
模块进行写操作。您需要将压缩的数组行转换为元组并将它们一起添加到np.array
到python数据类型。
>>> import csv
>>> writer = csv.writer(open('test.csv', 'w'))
>>> writer.writerows(tuple(f)+tuple(i) for f,i in zip(floats, ints))
>>> del writer
>>> print(open('test.csv').read())
0.0,5.0,10.0,15.0,20.0,25
30.0,35.0,40.0,45.0,50.0,55
60.0,65.0,70.0,75.0,80.0,85