1. 数组读写(注意bytes与str数据类型的相互转换)
(1)空格(制表符)分割的文本
1 import numpy as np
2 #生成目标文本
3 %%writefile myfile.txt
4 2.1 2.3 3.2 1.3 3.1
5 6.1 3.1 4.2 2.3 1.8
6 #常规读取方式(繁琐)
7 data = []
8 with open('myfile.txt') as f:
9 # 每次读一行
10 for line in f:
11 fileds = line.split()
12 row_data = [float(x) for x in fileds]
13 data.append(row_data)
14
15 data = np.array(data)
16 #使用loadtxt方法(简便)
17 data = np.loadtxt('myfile.txt')
(2)逗号分割文件(通常为.csv格式)
1 %%writefile myfile.txt
2 2.1, 2.3, 3.2, 1.3, 3.1
3 6.1, 3.1, 4.2, 2.3, 1.8
4 #常规方法,仅需将上述繁琐过程中的split的参数变为','即可
5 data = np.loadtxt('myfile.txt', delimiter=',') #指定分隔符参数
(3)loadtxt函数
loadtxt(fname, dtype=
comments='#', delimiter=None,
converters=None, skiprows=0,
usecols=None, unpack=False, ndmin=0)
skiprows
参数表示忽略开头的行数,可以用来读写含有标题的文本
1 %%writefile myfile.txt
2 X Y Z MAG ANG
3 2.1 2.3 3.2 1.3 3.1
4 6.1 3.1 4.2 2.3 1.8
5
6 np.loadtxt('myfile.txt', skiprows=1) #忽略第一行
注:genfromtxt函数功能更加全面,但是处理速度和效率会慢一点
1 %%writefile myfile.txt #写文件
2 -- BEGINNING OF THE FILE
3 % Day, Month, Year, Skip, Power
4 01, 01, 2000, x876, 13 % wow!
5 % we don't want have Jan 03rd
6 04, 01, 2000, xfed, 55
7
8 data = np.loadtxt('myfile.txt',
9 skiprows=1, #忽略第一行
10 dtype=np.int, #数组类型
11 delimiter=',', #逗号分割
12 usecols=(0,1,2,4), #指定使用哪几列数据
13 comments='%' #百分号为注释符
14 )
(4)自定义转换方法
1 %%writefile myfile.txt
2 2010-01-01 2.3 3.2
3 2011-01-01 6.1 3.1
4
5 import datetime
6
7 def date_converter(s): #自定义的转换方法
8 return datetime.datetime.strptime(s.decode('ascii'), "%Y-%m-%d") #保证输入参数为字符串
9
10 data = np.loadtxt('myfile.txt',
11 dtype=np.object, #数据类型为对象
12 converters={0:date_converter, #第一列使用自定义转换方法
13 1:float, #第二第三使用浮点数转换
14 2:float})
(5)读写各种格式的文件
(6)将数组写入文件
savetxt:将数组写入文件,默认使用科学计数法的形式保存
savetxt(fname,
X,
fmt='%.18e',
delimiter=' ',
newline='\n',
header='',
footer='',
comments='# ') //格式fmt,分隔符delimiter
1 data = np.array([[1,2],
2 [3,4]])
3
4 np.savetxt('out.txt', data)
5 with open('out.txt') as f:
6 for line in f:
7 print(line, end='')
8
9 data = np.array([[1,2],
10 [3,4]])
11
12 np.savetxt('out.txt', data, fmt="%d") #保存为整数
13 np.savetxt('out.txt', data, fmt="%.2f", delimiter=',') #保存为2位小数的浮点数,用逗号分隔
14
15 data = np.array([[1+1j,2],
16 [3,4]]) #复数值,默认会加上括号
17
18 np.savetxt('out.txt', data, fmt="%.2f", delimiter=',') #保存为2位小数的浮点数,用逗号分隔
(7)Numpy二进制格式
.npy
格式,多个数组保存为多个.npy
文件组成的 .npz
格式,每个 .npy
文件包含一个数组。shape, dtype
信息,以便完全重构出保存的数组。保存的方法:
save(file, arr)
保存单个数组,.npy
格式savez(file, *args, **kwds)
保存多个数组,无压缩的 .npz
格式savez_compressed(file, *args, **kwds)
保存多个数组,有压缩的 .npz
格式读取的方法:
load(file, mmap_mode=None)
对于 .npy
,返回保存的数组,对于 .npz
,返回一个名称-数组对组成的字典。1 a = np.array([[1.0,2.0], [3.0,4.0]])
2 #单个数组读写
3 fname = 'afile.npy'
4 np.save(fname, a)
5 aa = np.load(fname)
二进制与文本大小比较:
1 import os
2 a = np.arange(10000.)
3
4 np.savetxt('a.txt', a)
5 os.stat('a.txt').st_size #查看文件大小
6
7 np.save('a.npy', a)
8 os.stat('a.npy').st_size
注:二进制文件较小
1 a = np.array([[1.0,2.0],
2 [3.0,4.0]])
3 b = np.arange(1000)
4 #保存多个数组
5 np.savez('data.npz', a=a, b=b)
6 !unzip -l data.npz #使用!执行系统命令unzip查看里面包含的文件
7
8 data = np.load('data.npz') #载入数据
9
10 data.keys() #载入后可以像字典一样进行操作
11 data['a']
12 data['b'].shape
13
14 # 要先删除 data,否则删除时会报错
15 del data
16 os.remove('data.npz')
PermissionError: [WinError 32] 另一个程序正在使用此文件,进程无法访问。: 'data.npz'
压缩文件
#数据比较整齐时,压缩率较大
1 a = np.arange(20000.)
2 np.savez('a.npz', a=a) #无压缩
3 os.stat('a.npz').st_size
4 np.savez_compressed('a2.npz', a=a) #有压缩
5 os.stat('a2.npz').st_size
#数据比较混乱时,压缩率较小
6 a = np.random.rand(20000.)
7 np.savez('a.npz', a=a) #无压缩
8 os.stat('a.npz').st_size
9 np.savez_compressed('a2.npz', a=a) #有压缩
10 os.stat('a2.npz').st_size
2. 结构化数组
(1)可以使用 dtype
创造了自定义的结构类型,然后用自定义的结构来解释数组所占的内存
1 import numpy as np
2 a = np.array([1.0,2.0,3.0,4.0], np.float32)
3 a.view(np.complex64) #使用view方法,将a对应的内存按照复数来解释
4 my_dtype = np.dtype([('mass', 'float32'), ('vol', 'float32')])
# 将第一个浮点数解释为质量,第二个浮点数解释为速度,这段内存还可以看成是包含两个域(质量和速度)的结构体
5 a.view(my_dtype)
6 my_data = np.array([(1,1), (1,2), (2,1), (1,3)], my_dtype)
7 my_data[0] #第一个元素
8 my_data[0]['vol'] #第一个元素的速度域
9 my_data['mass'] #所有元素的质量域
10 my_data.sort(order=('vol', 'mass')) #自定义排序规则,先速度,后质量
11 person_dtype = np.dtype([('name', 'S10'), ('age', 'int'), ('weight', 'float')])
# 定义一个人的结构类型
12 people = np.empty((3,4), person_dtype) #产生3*4的空结构体数组
# 根据属性域,分别赋值
13 people['name'] = [['Brad', 'Jane', 'John', 'Fred'],
14 ['Henry', 'George', 'Brain', 'Amy'],
15 ['Ron', 'Susan', 'Jennife', 'Jill']]
16 people['age'] = [[33, 25, 47, 54],
17 [29, 61, 32, 27],
18 [19, 33, 18, 54]]
19 people['weight'] = [[135., 105., 255., 140.],
20 [154., 202., 137., 187.],
21 [188., 135., 88., 145.]]
22 people[-1, -1] #值为:('Jill',54,145.0)
(2)从文本中读取结构化数组
1 %%writefile people.txt
2 name age weight
3 amy 11 38.2
4 john 10 40.3
5 bill 12 21.2
6 #定义类型
7 person_dtype = np.dtype([('name', 'S10'), ('age', 'int'), ('weight', 'float')])
8 people = np.loadtxt('people.txt',
9 skiprows=1,
10 dtype=person_dtype) #指定类型
11 people['name'] #查看name域
12
13 %%writefile wood.csv
14 item,material,number
15 100,oak,33
16 110,maple,14
17 120,oak,7
18 145,birch,3
19
20 tree_to_int = dict(oak = 1,
21 maple=2,
22 birch=3)
23 #定义转换函数,使之对应于整数
24 def convert(s):
25 return tree_to_int.get(s.decode('utf-8'), 0) #将bytes数据转换成string类型;如仅使用s,则将都转换成默认值0
26
27 data = np.genfromtxt('wood.csv',
28 delimiter=',', # 逗号分隔
29 dtype=np.int, # 数据类型
30 names=True, # 从第一行读入域名作为属性名称
31 converters={1:convert}
32 )
33
34 data['material'] #查看域
(3)嵌套类型
#定义嵌套类型:位置(x,y)、质量
1 particle_dtype = np.dtype([('position', [('x', 'float'),
2 ('y', 'float')]),
3 ('mass', 'float')
4 ])
5
6 %%writefile data.txt
7 2.0 3.0 42.0
8 2.1 4.3 32.5
9 1.2 4.6 32.3
10 4.5 -6.4 23.3
11
12 data = np.loadtxt('data.txt', dtype=particle_dtype) #读取数据
13 data['position']['x'] #访问位置中嵌套的x轴数据
3. 记录数组(record array)
1 import numpy as np
2 #定义质点类型
3 partical_dtype = np.dtype([('mass', 'float'),
4 ('velocity', 'float')])
5
6 from numpy import rec #生成记录数组需要使用numpy.rec里的fromrecords
7 particals_rec = rec.fromrecords([(1,1), (1,2), (2,1), (1,3)],
8 dtype = partical_dtype)
9
10 particals_rec.mass #通过属性访问域
11 particals_rec['mass'] #直接查看域
注:记录数组的运行效率要比结构化数组要慢一些
#定义结构化数组
1 particals = np.array([(1,1), (1,2), (2,1), (1,3)],
2 dtype = partical_dtype)
3 #使用view方法将结构化数组看成记录数组
4 particals_rec = particals.view(np.recarray)
5 particals_rec.mass #访问域
6 particals_rec.velocity
7 particals.dtype.names #对于自定义类型particals.dtype,通过names属性查看有哪些域
4. 内存映射:内存映射文件与虚拟内存有些类似,通过内存映射文件可以保留一个地址空间的区域,同时将物理存储器提交给此区域;内存文件映射的物理存储器来自一个已经存在于磁盘上的文件,而且在对该文件进行操作之前必须首先对文件进行映射。
使用内存映射文件处理存储于磁盘上的文件时,将不必再对文件执行I/O操作(速度快),使得内存映射文件在处理大数据量的文件时能起到相当重要的作用。
主要函数有:
memmap
frombuffer
ndarray constructor
其中,memmap(filename,
dtype=uint8,
mode='r+',
offset=0,
shape=None,
order=0)
mode表示文件被打开的类型:
r
只读c
复制+写,但是不改变源文件r+
读写,使用 flush
方法会将更改的内容写入文件w+
写,如果存在则将数据覆盖offset表示从第几个位置开始
参考资料:
1、《Introducing Python》
2、《像计算机科学家一样思考Python》
3、《Python编程:从入门到实践》
4、《Python编程实战:运用设计模式、并发和程序库创建高质量程序》
5、《自学Python——编程基础、科学计算及数据分析》
6、 https://github.com/lijin-THU/notes-python