参考资料:
https://github.com/lijin-THU/notes-python(相应实体书为:《自学Python——编程基础、科学计算及数据分析》)
https://www.jianshu.com/p/57e3c0a92f3a (NumPy Tutorial - TutorialsPoint教程)
Numpy学习
import numpy as np 或 from numpy import * //在ipython中可以使用 %pylab 快速导入numpy和matplotlib
一、数组array //数组可以进行数学操作,对应元素进行+、-、*(非矩阵乘法)、/等
a = [1, 2, 3, 4]; a = np.array(a); //列表转化为数组,等价于a = array([1, 2, 3, 4])
1. 基本属性
- type(a) //查看数组类型:numpy.ndarray
- a.dtype //查看数组中的数据类型,如dtype('int32')
- a.itemsize //查看数组中每个元素占的字节数,如4;查看数组所有元素所占空间用a.nbytes
- a.shape //查看数组形状,返回元组,如(4,)代表一个秩为1的数组;或者 shape(a) shape()也可以作用于列表类型
- a.size //查看元素数目,或者size(a)
- a.ndim //查看数组维数
- a.fill(-4.8) //使用 fill 方法将数组设定为指定值;数组要求元素类型与dtype一致,不一致时会进行类型转换,此处结果为 array([-4, -4, -4, -4])
2. 索引和切片
(1)数组的基本切片在内存中使用的是引用机制(基本切片返回视图)
1 a = array([0,1,2,3,4]) 2 b = a[2:4] #python并没有为b分配新的空间来存储它的值,而是让b指向了a所分配的内存空间 3 b[0] = 10 #因此,改变b会改变a的值;此时a为array([ 0, 1, 10, 3, 4])
#这种现象在列表中不会出现
a = [1,2,3,4,5]
b = a[2:3]
b[0] = 13234
print a #a仍然为[1,2,3,4,5]
- 优点:对于很大的数组,不用大量复制多余的值,节约空间
- 缺点:出现改变一个值改变另一个值的情况
- 解决方案:使用copy()方法,申请新内存产生一个复制,如b = a[2:4].copy()
(2)花式索引(常规切片只能支持连续或者等间隔的切片操作)——高级索引返回数据副本(新内存)
注:花式索引返回的是原对象的一个复制(新内存)而不是引用
- 一维花式索引(位置或布尔数组)
1 a = arange(0, 80, 10) #产生等差数组 2 indices = [1, 2, -3] #指定索引位置 3 y = a[indices] 4 5 mask = array([0,1,1,0,0,1,0,0], dtype=bool) #生成布尔数组 6 a[mask] 7 8 from numpy.random import rand 9 a = rand(10) 10 mask = a > 0.5 #用布尔表达式生成布尔数组mask 11 a[mask]
- 二维花式索引(需要给定行row和列col的值)
1 a = array([[ 0, 1, 2, 3, 4, 5], 2 [10,11,12,13,14,15], 3 [20,21,22,23,24,25], 4 [30,31,32,33,34,35], 5 [40,41,42,43,44,45], 6 [50,51,52,53,54,55]]) 7 a[(0,1,2,3,4), (1,2,3,4,5)] #返回次对角线上的5个值 8 a[3:, [0,2,5]] #返回最后三行的第1,3,5列
#使用mask进行索引
9 mask = array([1,0,1,0,0,1], dtype=bool)
10 a[mask, 2]
- where语句:where(array) //返回所有非零元素的索引
3. 数组类型
(1)整数数组
(2)浮点数数组
(3)布尔数组
(4)复数数组:a = array([1 + 1j, 2, 3, 4])
- 数组类型a.dtype = dtype('complex128')
- 实部:a.real array([1., 2., 3., 4.])
- 虚部:a.imag array([1., 0., 0., 0.])
- 复共轭:a.conj()
(5)指定/改变数组类型 a = array([0,1.0,2,3], dtype=float32)
Numpy类型
(6)asarray()函数:asarray不会修改原来数组的值,但当类型相同的时候,asarray并不会产生新的对象,而是使用同一个引用
1 a = array([1.5, -3], dtype=float32) 2 asarray(a, dtype=float64) #不修改原数组a 3 asarray(a, dtype=uint8) #不修改原数组a 4 b = asarray(a, dtype=float32) 5 b is a #True 使用同一个引用
优点:不仅可以作用于数组,还可以将其他类型转化为数组。例如,为了保证我们的输入值是数组,我们需要将其使用asarray进行转化,当输入已经是数组时,不会产生新的对象,保证了效率。
(7)astype()方法:返回一个新数组(新内存) a.astype(float64)
注:astype也不改变原数组,但是总是返回原来数组的一份复制,即使转换的类型是相同的
(8)view()方法:共用一块内存
1 a = array((1,2,3,4), dtype=int32) 2 b = a.view(uint8) #view会将a
在内存中的表示看成是uint8
进行解析 3 a[0] = 2**30 #a 和 b 共用一块内存,修改a
会修改b
的值
4. 数组常用方法 a = array([ [1,2,3], [4,5,6] ]) //对于二维数组,列为第一维(axis=0),行为第二维(axis=1)
(1)求和:sum(a, axis=维度)或者 a.sum(axis=维度) 不指定维度则对所有元素求和 //函数形式、方法形式
(2)求积:prod(a, axis=维度)或者 a.prod(axis=维度) 不指定维度则对所有元素求和 //函数形式、方法形式
(3)求最大最小值及其相应位置min()、max()、argmin()、argmax()
1 from numpy.random import rand 2 a = rand(3, 4) 3 a.min() #全局最小 4 a.min(axis=0) #沿某个轴最小 5 a.argmin() #全局最小值位置 6 a.argmin(axis=0) #沿某个轴最小值位置
(4)均值mean()、average()
1 a = array([[1,2,3],[4,5,6]]) 2 a.mean() #全局平均 "方法" 3 a.mean(axis=-1) #沿某轴平均 4 mean(a) #mean函数 5 average(a, axis = 0) #average函数 6 average(a, axis = 0, weights=[1,2]) #加权平均
(5)标准差、方差std()、var()
1 a.std(axis=1) #方法 2 a.var(axis=1) 3 std(a, axis=1) #函数 4 var(a, axis=1)
(6)将数值限制在某个范围 clip(),如 a.clip(3,5) //将小于3的变成3,大于5的变成5
(7)计算最大值和最小值之差 ptp(),如a.ptp()、a.ptp(axis=1)
(8)近似方法 round()
1 a = array([1.35, 2.5, 1.5]) 2 a.round() #.5的近似规则为近似到偶数值 3 a.round(decimals=1) #近似到一位小数
5. 数组排序
sort()函数:返回从小到大排列的新数组,不改变原数组
sort()方法:返回从小到大排列的数组,改变原数组;对于多维数组,sort方法默认沿着最后一维开始排序(如对于二维数组,默认对行进行排序)
argsort()函数、argsort()方法:返回从小到大的排列在数组中的索引位置,不改变原数组
1 %pylab 2 names = array(['bob', 'sue', 'jan', 'ad']) 3 weights = array([20.8, 93.2, 53.4, 61.8]) 4 5 sort(weights) 6 ordered_indices = argsort(weights) 7 weights[ordered_indices] 8 data.argsort() 9 data.sort() #改变原数组
searchsorted(sorted_array, values)函数:接受两个参数,第一个必须是已排序的数组,第二个为查找的值,返回值为“保持第一个数组的排序性质不变,将第二个数组中的值插入第一个数组中的位置”
1 from numpy.random import rand 2 data = rand(100) 3 data.sort() 4 bounds = .4, .6 #不加括号,默认是元组,等价于(0.4, 0.6) 5 low_idx, high_idx = searchsorted(data, bounds) #返回这两个值对应的插入位置 6 data[low_idx:high_idx] #利用插入位置,将数组中所有在这两个值之间的值提取出来
6. 数组形状
(1)修改数组形状
1 %pylab 2 a = arange(6) 3 a.shape = 2,3 #修改原数组形状 4 a.reshape(3,2) #返回修改后的新数组,不修改原数组
注:shape 和 reshape 方法不能改变数组中元素的总数,否则会报错
(2)增加数组维数:newaxis //不修改原数组
1 a = arange(3) 2 shape(a) #(3,) 3 y = a[newaxis, :] 4 shape(y) #(3,1) 5 y = a[:, newaxis] 6 shape(y) #(1,3) 7 y = a[newaxis, newaxis, :] #增加多个维数 8 shape(y) #(1,1,3)
(3)去除多余的轴:squeeze //返回一个将所有长度为1的维度去除的新数组
1 a = arange(6) 2 a.shape = (2,1,3) 3 b = a.squeeze() 4 b.shape #(2,3)
(4)数组转置:a.transpose()或者a.T //对于复数数组,转置并不返回复共轭,只是单纯的交换轴的位置
#多维数组转置
1 a = arange(60) 2 a.shape = 3,4,5 3 b = a.T 4 b.shape #(5,4,3) 转置只是交换了轴的位置
注:转置返回的是对原数组的另一种view,所以改变转置会改变原来数组的值
(5)数组连接:concatenate((a0, a1, ..., aN), axis=0) //除了给定的连接轴外,这些数组其他轴的长度必须一致
1 x = array([ [0,1,2], [10,11,12] ]) #x.shape=(2,3)
2 y = array([ [50,51,52], [60,61,62] ]) #y.shape=(2,3)
3 z = concatenate((x,y)) #默认沿着第一维进行连接,z.shape=(4,3);等价于 vstack((x, y)) 4 z = concatenate((x,y), axis=1) #沿着第二维进行连接,z.shape=(2,6);等价于 hstack((x, y)) 5 z = array((x,y)) #x
和y
的形状是一样的,可以将它们连接成三维的数组,z.shape=(2,2,3);等价于 dstack((x, y))
(6)将多维数组转化为1维数组:flatten()方法、flat属性、ravel()方法
1 a = array([ [0,1], [2,3] ]) 2 b = a.flatten() #b = array([0,1,2,3]),返回的是数组的复制,修改b并不会影响a 3 4 b = a.flat #a.flat 相当于返回了所有元组组成的一个迭代器,即b为numpy. 5 print(b) #b为numpy.flatiter,修改b会影响a 6 a.flat[:] #array([0,1,2,3]) 7 8 b = a.ravel() #b为array([0,1,2,3]),但是修改b会影响a 9 10 a = array([ [0,1], [2,3] ]) 11 aa = a.transpose() 12 b = aa.ravel() #在这种情况下,修改b并不会改变aa和a的值,原因是我们用来ravel的对象 aa 本身是 a 的一个view
(7)保证数组至少有x维:atleast_xd()函数;x可以取值1,2,3
1 x = 1 2 atleast_1d(x) #输出array([1]) 3 a = array([1,2,3]) #(3,) 4 b = atleast_2d(a) #b为array([[1,2,3]]) 5 b.shape #(1,3) 6 c = atleast_3d(b) #c为array([[[1],[2],[3]]]) 7 c.shape #(1,3,1)
SciPy中用来保证输入满足一定条件的函数
7. 查看对角线元素:diagonal()
1 import numpy as np 2 a = np.array([11,21,31,12,22,32,13,23,33]) 3 a.shape = 3,3 4 a.diagonal() #查看对角线元素 5 #使用偏移查看次对角线 6 a.diagonal(offset=1) #正数表示右移 7 a.diagonal(offset=-1) #负数表示左移 8 #花式索引对角线元素 9 i = [0,1,2] 10 a[i, i] 11 a[i, i] = 2 #更新对角线值 12 #更新次对角线值 13 i = np.array([0,1]) #定义为数组,便于实现+1操作 14 a[i, i + 1] = 1 15 a[i + 1, i] = -1
8. 数组与字符串的转换,tostring()、fromstring()
1 import numpy as np 2 a = np.array([[1,2], [3,4]], dtype = np.uint8) 3 a.tostring() #转化为字符串,按照行进行转换 4 a.tostring(order='F') #使用Fortran格式,按照列读取数据 5 s = a.tostring() 6 a = np.fromstring(s, dtype=np.uint8) #从字符串中读出数据,需要指定数据类型,返回一维数组 7 a.shape = 2,2 #重新设定数组维度
- 对于文本文件,推荐使用:
loadtxt、
genfromtxt、
savetxt
- 对于二进制文件,推荐使用:
save、
load、
savez
二、matplotlib
(可参考《python绘图工具基础-matplotlib学习之基本使用》——https://mp.weixin.qq.com/s/0gijX0Xn24tmui5pT1Zx9Q)
注:在脚本中使用 plot 时,通常图像是不会直接显示的,需要增加 show() 选项,只有在遇到 show() 命令之后,图像才会显示
1 %matplotlib inline 2 x = linspace(0, 2 * pi, 50) #生成一组等间隔的数据 3 plot(sin(x)) #默认以下标为x轴 4 plot(x, sin(x)) #给定x轴 5 plot(x, sin(x), x, sin(2 * x)) # 多条数据线;默认输入多次画图会自动叠加(不覆盖),如plot(x);plot(y);
# 可以跟Matlab类似用 hold(False) 关掉,这样新图覆盖旧图;hold(True)恢复原先设定 6 plot(x, sin(x), 'r-^') # 指定线条参数 7 plot(x, sin(x), 'b-o', x, sin(2 * x), 'r-^') 8 plot(x, sin(x), 'bo') # 散点图绘制方法一 9 scatter(x, sin(x)) # 散点图绘制方法二:scatter()函数 10 x = rand(200) 11 y = rand(200) 12 size = rand(200) * 30 13 color = rand(200) 14 scatter(x, y, size, color) # 指定散点图大小、颜色参数 15 colorbar() # 显示颜色条 16 t = linspace(0, 2*pi, 50) 17 x = sin(t) 18 y = cos(t) 19 figure() # 使用figure()命令产生新的图像,以绘制多图 20 plot(x) 21 figure() 22 plot(y) 23 subplot(1, 2, 1) # 绘制单张图的子图,subplot(row, column, index) 24 plot(x) 25 subplot(1, 2, 2) 26 plot(y)
- label参数添加标签:plot(x, label='sin')
- legend()参数添加图例:legend()或者legend(['sin', 'cos']) 将标签和图例合并
1. 设置坐标轴标签和标题
1 plot(x, sin(x)) 2 xlabel('radians') 3 # 可以设置字体大小 4 ylabel('amplitude', fontsize='large') 5 title('Sin(x)')
6 grid() #显示网格
- 清除、关闭图像:clf() 清除已有图像;close() 关闭当前图像;close('all') 关闭所有图像
2. imshow显示图像:
1 from scipy.misc import ascent #或者face图像,lena图像已被取消 2 img = ascent() #获取图像数据,或者face() 3 img.shape 4 imshow(img, 5 # 设置坐标范围 6 extent = [-250, 250, -250, 250], 7 # 设置colormap 8 cmap = cm.bone) #cm表示colormap,可以用dir(cm)查看看它的种类 9 colorbar() 10 imshow(img, cmap=cm.RdGy_r) #使用不同的colormap会有不同的显示效果
- 生成直方图:hist(randn(1000)) //利用高斯分布随机生成1000个点绘制直方图