numpy是一个科学计算库,专门用于矩阵,可以代替matlab的一些矩阵操作与计算。本篇内容的原型为某站200集AI教程的学习所得,后来经过博主结合其他博客,深化学习,产生了本篇博文。

文章目录

  • ​​环境介绍​​
  • ​​numpy的IO库​​
  • ​​numpy建立矩阵​​
  • ​​shape打印矩阵形状​​
  • ​​dtype打印矩阵里面元素的类型​​
  • ​​numpy索引读取数据​​
  • ​​numpy切片​​
  • ​​对numpy.array中所有元素做整体操作​​
  • ​​bool值当索引​​
  • ​​矩阵元素的与、或条件筛选​​
  • ​​矩阵元素的类型转换​​
  • ​​矩阵求极值​​
  • ​​求和(按照行或者列)​​
  • ​​指数计算/开平方根​​
  • ​​初始化0矩阵和1矩阵​​
  • ​​矩阵的操作​​
  • ​​reshape重置矩阵的形状​​
  • ​​矩阵的横向纵向拼接​​
  • ​​矩阵的横向纵向切割​​
  • ​​关于矩阵复制​​
  • ​​赋值符号​​
  • ​​浅复制​​
  • ​​深复制​​
  • ​​排序和索引​​
  • ​​最值​​
  • ​​扩展​​
  • ​​排序​​
  • ​​总结​​
  • ​​参考资料​​

环境介绍

整个博文是在anaconda平台上基于python3.7实现的。

numpy的IO库

numpy提供了下列的IO函数:

save():将ndarray对象保存为.npy文件,为二进制文件
load():从.npy文件中获取ndarray对象
savetxt():将ndarray对象保存为.txt文件
loadtxt():从.txt文件中获取ndarray对象

简单用代码实现一下:

# 案例1,模拟读取txt

```python
from io import StringIO
import numpy as np
s = StringIO(u"1,1.3,abcde")
data = np.genfromtxt(s, dtype=[('myint','i8'),('myfloat','f8'), ('mystring','S5')], delimiter=",")
data

输出:
array((1, 1.3, b’abcde’),dtype=[(‘myint’, ‘<i8’), (‘myfloat’, ‘<f8’), (‘mystring’, ‘S5’)])
#案例2 ,真实读取txt文件,txt文件要规范,比如换行规范+用,隔开。

import numpy
world_alcohol = numpy.genfromtxt("word_alcohol.txt", delimiter=",",dtype=str)
#上面一句话是:实例化一个numpy.genfromtxt的对象,第一参数传要读取的文件名,第二个是分割符(每一行看作一条数据,逗号区分每个数据的属性),最 #后一个读取后的数据类型。这是用numpy.genfromtxt读取txt文件内容的方法。如果实际类型是时间,可以读进来再转化。
print(type(world_alcohol)) # <class 'numpy.ndarray'>
print(world_alcohol) # 打印ndarray对象的内容
print(help(numpy.genfromtxt)) # help函数,解释参数函数的用法。

#案例3,读取txt中的数据,且按照对应的格式,读取出来是一个对象列表,也可以理解为是一个一维矩阵

import numpy as np
data = np.genfromtxt("word_alcohol.txt", dtype=[('myint','i8') ,('mystring1','S5'), ('mystring2','S5') ,('mystring3','S5'),('myfloat','f8')], delimiter=",",skip_header=1)
#data = np.genfromtxt("word_alcohol.txt", delimiter=",",dtype=str,skip_header=1)
print(data)
#print(help(np.genfromtxt))

打印输出:

array([(1986, b'Weste', b'Viet ', b'Wine', 0. ),
(1986, b'Ameri', b'Urugu', b'Other', 0.5)],
dtype=[('myint', '<i8'), ('mystring1', 'S5'), ('mystring2', 'S5'), ('mystring3', 'S5'), ('myfloat', '<f8')])

numpy建立矩阵

如何利用numpy框架建立一个矩阵。

vector = numpy.array([5, 10, 15, 20])  #使用numpy.array方法把一个list转化为一个向量或者叫一行矩阵。
matrix = numpy.array([[5, 10, 15], [20, 25, 30], [35, 40, 45]])  #使用numpy.array方法把多个list转化为一个矩阵。
print(vector)
print(matrix)

总结:所以写一维矩阵写一个中括号,写二维矩阵写二个中括号,写三维矩阵写三个中括号。

shape打印矩阵形状

vector = numpy.array([5, 10, 15, 20])
print(vector.shape)  #vector.shape就是打印该矩阵的形状,即几维,几行几列。
matrix = numpy.array([[5, 10, 15], [20, 25, 30], [35, 40, 45]])
print(matrix.shape)  #matrix.shape就是打印该矩阵的形状,即几维,几行几列。
一般XXX.shape用作调试程序用。可以直接输出。
输出:
  (4,) # 一行四列
  (3, 3) # 3行3列 2维

在numpy的矩阵中,不像是list,你想放什么就放什么,是有格式要求的。里面必须是相同的结构,

dtype打印矩阵里面元素的类型

构建numpy矩阵时,要求里面的元素都是一样的类型,如果已有的整型/字符型/浮点型,满足不了需要,可以在读取的时候定义读取单个数据的dtype。就好像上面的读取txt文档的例子,不过这种定义dtype的类型一般读出来就是一维矩阵,类似一个java中list。

numbers = numpy.array([1, 2, 3, 4])
print(numbers)
print(numbers.dtype)

输出:
  [1 2 3 4]
  int32
当上述代码修改成下面时:

numbers = numpy.array([1, 2, 3, 4.0])
print(numbers)
print(numbers.dtype)

输出:
  [ 1. 2. 3. 4.]
  float64
如果其中一个改成字符串,那么最终的类型就是都是字符串。因为矩阵里面的类型要一致这个规则的限制,如果矩阵里面元素的基本类型不统一,会自动转型为高级类型,转型顺序:int < float < string。

numpy索引读取数据

import  numpy
world_alcohol = numpy.genfromtxt("world_alcohol.txt", delimiter=",", dtype="U75", skip_header=1)
print(world_alcohol)
uruguay_other_1986 = world_alcohol[1,4]  #我们需要取的数据是第2行第5个,同list第一个数据索引值为0
third_country = world_alcohol[2,2]    #这行我们需要取的数据是第3行第3个。
print(uruguay_other_1986)
print(third_country)

需要注意的是索引从0开始,用中括号读取,第一个数字是第一个维度,第n个数字是第n个维度。
输出:
  0.5
  Cte d’Ivoire

numpy切片

切片,是把已有的矩阵取出来一个区域,待操作的矩阵可以是一维的也可以是多维的。
切片的规则:顾头不顾腚,即包含起始位置,不包含结束位置。
1)向量的切片

vector = numpy.array([5, 10, 15, 20])  #建立一个向量
print(vector[0:3])  #向量与list的切片方式一致,顾头不顾尾。也就是取0-1-2位置的三个数字。

输出:
[ 5 10 15]
2)矩阵的单列或单行切片,技巧使用冒号表示所有行或者列,也就是说可以单独拿出来某一行或者某一列。

matrix = numpy.array([
[5, 10, 15],
[20, 25, 30],
[35, 40, 45]
])  #建立矩阵
print(matrix[:,1])  # :表示这一行或一列的所有元素。以“,”为间隔,隔开行和列的位置(这里要区分索引用分号控制下标)。如果在第一个位置为行,第二个位置为列。

输出:
  [10 25 40]
3)矩阵的多列或多行切片,采用切片的规则,顾头不顾腚

matrix = numpy.array([
[5, 10, 15],
[20, 25, 30],
[35, 40, 45]
])
print(matrix[:,0:2])  #以","为间隔,隔开行和列的位置。":"表示所有元素。 截取所有行的0和1列,这是做的切片,顾头不顾尾
输出:
  [[ 5 10]
  [20 25]
  [35 40]]

matrix = numpy.array([
[5, 10, 15],
[20, 25, 30],
[35, 40, 45]
])
print(matrix[1:3,0:2])
# 截取第1-2行,第0-1列

输出:
[[20 25]
[35 40]]

对numpy.array中所有元素做整体操作

对numpy.array整体的操作=对numpy.array每一个元素做相同的操作。用变量做大于小于等于的操作,就可以得出矩阵里每个元素比较结果的矩阵。

vector = numpy.array([5, 10, 15, 20])
print(vector == 10)

output:
[False True False False]

这一条定律对矩阵一样适用:

matrix = numpy.array([
  [5, 10, 15],
  [20, 25, 30],
  [35, 40, 45]
  ])
print(matrix == 25)

output:
  [[False False False]
  [False True False]
  [False False False]]

总结:可以把比较的结果设置成一个变量,这样就能取出对应的符合条件的值了。

bool值当索引

上面的例子我们筛选出了符合条件的数据,形成了一个筛选结果矩阵。但是如何把这些符合筛选条件的元素取出来。
可以用bool值当索引。
方法:把某个矩阵的对应布尔值矩阵作为索引传递给原矩阵,则会返回出bool值为真的元素

vector = numpy.array([5, 10, 15, 20])
equal_to_ten = (vector == 10)
print(equal_to_ten)
print(vector[equal_to_ten])

output:
  [False True False False]
  [10]

上述规律对矩阵一样适用: 定位列之后,拿出来那一行的写法

matrix = np.array([
[5, 10, 15],
[20, 25, 30],
[35, 40, 45]
])
second_column_25 = (matrix[:,1] == 25) #单独拿出第1列与25比较,找出等于25的值
print(second_column_25)
print(matrix[second_column_25, :]) #会选出为true的那一行,second_column_25是所在的行号,:是取出该行的所有列

output:
[False True False]
[[20 25 30]]

矩阵元素的与、或条件筛选

1)bool值表的与,,用“&”表示

vector = numpy.array([5, 10, 15, 20])
#即等于10 又等于 5
equal_to_ten_and_five = (vector == 10) & (vector == 5)
print(equal_to_ten_and_five)

output:  
  [False False False False]
2)bool值表的或,用“|”表示

vector = numpy.array([5, 10, 15, 20])
#等于10 或者 等于 5
equal_to_ten_and_five = (vector == 10) | (vector == 5)
print(equal_to_ten_and_five)
结果:

[True True False False]

矩阵元素的类型转换

字符串在符合规则的情况下,可以转换为int或者float类型。

vector = np.array(["11", "2", "3"])#元素为字符串类型
print(vector.dtype)#打印元素类型 python 3 需要括号
print(vector)
vector = vector.astype(float)#用astype()方法进行强制类型转换。
print (vector.dtype)
print (vector)

输出结果:
<U2 #数字代表字符串的长度,可以这么理解,unicode2
[‘11’ ‘2’ ‘3’]
float64
[11. 2. 3.]

矩阵求极值

获得矩阵的最大值,最小值。

vector = np.array([5, 10, 15, 20])
print(vector.min())#求矩阵中最小的元素
print(vector.max()) #求矩阵中最小的元素
#print(help(np.array))#想了解更多的方法或函数,打印相关帮助即可

求和(按照行或者列)

matrix = numpy.array([
[5, 10, 15],
[20, 25, 30],
[35, 40, 45]
])
matrix.sum(axis=1)  #按行求和,参数axis=1
#output:array([ 30, 75, 120])
matrix.sum(axis=0)  #按列求和,参数axis=0
#output:array([60, 75, 90])

指数计算/开平方根

B = np.arange(3)# 生成一个[0 1 2]的一维矩阵,3为结束项
print(B)
print (np.exp(B))#exp是以e为底数,B的每个元素分别作为指数进行计算,计算结果以矩阵的方式显示
print (np.sqrt(B))#sqrt是对B的每个元素分别开根号,计算结果以矩阵的方式显示

输出结果:
[0 1 2]
[1. 2.71828183 7.3890561 ]
[0. 1. 1.41421356]

初始化0矩阵和1矩阵

可以利用numpy提供的api快速初始化指定维度的0矩阵和1矩阵,也就是矩阵的元素是0或者1.

zero_array = np.zeros((3,4))
print(zero_array)
one_array = np.ones((3,4),dtype=int)
print(one_array)

输出0矩阵或者1矩阵。如下:
[[1 1 1 1]
[1 1 1 1]
[1 1 1 1]]

矩阵的操作

a = np.floor(10*np.random.random((3,4)))   #np.random.random((3,4)) 是0到1之间的随机浮点数3行4列,*10让数据扩大10倍便于分辨,floor方法是向下取整又叫舍尾法近似。
print(a)
print("----")
print(a.ravel())#a.ravel() 方法是把一个二维矩阵拉伸成一个1维向量,顺序是先第1行从左到右,然后第2行从左到右,以此类推
print("----")
a.shape = (6, 2)#把矩阵a的形状设置为6行2列
print(a)
print("----")
print(a.T)#把a矩阵转置,即把原来的第一列变为新矩阵的第一行,第二列变为新矩阵的第二行,即原来的行变为列,原来的列变为行,依次类推。

代码的输出为:

2.python包-numpy总结01_数据

reshape重置矩阵的形状

print("----")
#reshape(3,-1)方法是修改矩阵的形状,3是3行,-1这个数表示让计算机根据其他维度的数据.
#自动算出-1这个地方应该填写多少,并完成修改。矩阵的拼接:
print(a.reshape(3,-1))

代码的输出:

2.python包-numpy总结01_txt文件_02

矩阵的横向纵向拼接

主要是np的两个常用函数hstack,vstack。

a = np.floor(10*np.random.random((2,2)))
b = np.floor(10*np.random.random((2,2)))
print("------")
print(a)
print("------")
print(b)
print("------")
print(np.hstack((a,b)))# hstack方法是矩阵横向拼接方法
print("------")
print(np.vstack((a,b)))# hstack方法是矩阵纵向拼接方法
print("------")

代码的输出为:

------
[[5. 5.]
[2. 5.]]
------
[[6. 4.]
[5. 7.]]
------
[[5. 5. 6. 4.]
[2. 5. 5. 7.]]
------
[[5. 5.]
[2. 5.]
[6. 4.]
[5. 7.]]
------

矩阵的横向纵向切割

矩阵的切分:

a = np.floor(10*np.random.random((2,12)))
print(a)
print("------")
print (np.hsplit(a,3))# hsplit函数是横向切割,传入两个参数,第一个参数是要被切割的矩阵,第二个是切成几份。
print("------")
print (np.hsplit(a,(3,4)))# hsplit还有一种用法,指定在某几个位置切。该例子中,第二个位置参数是一个元组形式,表示在位置3,4分别切一刀
print("-----分割线----")
a = np.floor(10*np.random.random((12,2)))
print(a)
print("------")
np.vsplit(a,3)# vsplit函数是纵向切割,传入两个参数,第一个参数是要被切割的矩阵,第二个是切成几份。也可以做指定位置切割:

代码输出:

[[2. 7. 2. 9. 8. 6. 5. 4. 9. 9. 6. 5.]
[3. 6. 3. 3. 6. 8. 0. 7. 6. 5. 0. 1.]]
------
[array([[2., 7., 2., 9.],
[3., 6., 3., 3.]]), array([[8., 6., 5., 4.],
[6., 8., 0., 7.]]), array([[9., 9., 6., 5.],
[6., 5., 0., 1.]])]
------
[array([[2., 7., 2.],
[3., 6., 3.]]), array([[9.],
[3.]]), array([[8., 6., 5., 4., 9., 9., 6., 5.],
[6., 8., 0., 7., 6., 5., 0., 1.]])]
-----分割线----
[[5. 4.]
[0. 1.]
[8. 2.]
[7. 0.]
[4. 4.]
[5. 0.]
[9. 7.]
[7. 1.]
[8. 4.]
[5. 8.]
[4. 3.]
[8. 4.]]
------
[array([[5., 4.],
[0., 1.],
[8., 2.],
[7., 0.]]), array([[4., 4.],
[5., 0.],
[9., 7.],
[7., 1.]]), array([[8., 4.],
[5., 8.],
[4., 3.],
[8., 4.]])]

关于矩阵复制

赋值符号

指向一样,数据共享,内存空间是一块,类似一个人有两个名字,这不是真的复制。

a = np.arange(12)#建立一个12个元素的向量,命名为a
b = a
print(b is a)#打印判断b是不是a的结果
b.shape = (3,4)#把一维向量b的形状转化成3行4列的而二维矩阵
print (a.shape)#打印a的形状
print (id(a))#打印a的id,id是某个变量在内存中生成时,被赋予的具有唯一性的内存标识
print (id(b))#打印b的id

打印输出:

True
(3, 4)
4834999312
4834999312

浅复制

指向不同,但数据共享。

c = a.view()# 矩阵的view方法是浅复制,即c和a指向不同,但又同时共享着数据
print(c is a)#打印c是不是a的结果
c.shape = (2,6)
print (a.shape)
c[0,4] = 1234#把矩阵c第1行第5列元素赋值为1234
print (a)

output:

False
(3, 4)
[[ 0 1 2 3]
[1234 5 6 7]
[ 8 9 10 11]]

由此得出,矩阵的view方法是浅复制,即c和a指向不同,但又同时共享着数据。

深复制

想要完全

d = a.copy() # 矩阵的copy方法是深复制,即d和a指向不同,数据不同
print(d is a)
d[0,0] = 9999
print(d)
print(a)

output:

False
[[9999 1 2 3]
[1234 5 6 7]
[ 8 9 10 11]]
[[ 0 1 2 3]
[1234 5 6 7]
[ 8 9 10 11]]

排序和索引

最值

data = np.sin(np.arange(20)).reshape(5,4)  #随机创建一个矩阵
print(data)
print("----")
ind = data.argmax(axis=0)#矩阵的argmax方法是求每列或每行的最大值,axis=0这个参数指按列统计(结果是该列的第几行最大,方便后面拿出来),axis=1是按行统计。
print(ind)
print("----")
print(data.shape)
print(data.shape[1]) #取出来具体的列的数目
print(data.shape[0]) #取出来具体的行的数目
print("----")
data_max = data[ind, range(data.shape[1])]#把每列最大的元素取出来。 2行0列,0行1列,3行2列,1行3列
print(data_max)

range() 函数可创建一个整数列表,一般用在 for 循环中。
data.shape[1] 是列数 data.shape[0] 是行数
关于np.sin(array),是获得矩阵里元素的正弦值。相关的资料可以查看:https://www.runoob.com/numpy/numpy-mathematical-functions.html

扩展

a = np.arange(0, 40, 10) #随机建立一个矩阵,从0到40,step为10,遍历出0-10-20-30  
print(a)
print("---")
b = np.tile(a, (3, 5)) # tile方法是矩阵拓展方法,第一参数是把a作为整体当做一个元素进行扩展,第二个参数是扩展成3行5列的矩阵。
print(b)

输出的结果:

[ 0 10 20 30]
---
[[ 0 10 20 30 0 10 20 30 0 10 20 30 0 10 20 30 0 10 20 30]
[ 0 10 20 30 0 10 20 30 0 10 20 30 0 10 20 30 0 10 20 30]
[ 0 10 20 30 0 10 20 30 0 10 20 30 0 10 20 30 0 10 20 30]]

排序

a = np.array([[4, 3, 5], [1, 2, 1]])
print(a)
print("----")
b = np.sort(a, axis=1)#按照行对矩阵a排序,默认是从小到大排序,把新矩阵赋值给b
print(b)
print("----")
a.sort(axis=1)# 这种调用方法和np.sort(a,axis=1)效果一样
a = np.array([4, 3, 1, 2])
j = np.argsort(a)# argsort方法是先对矩阵a排序,然后对应求出每个元素在原来矩阵a中的索引
print (j)
print (a[j]) #把这个索引传入原矩阵就可以得到排序后的新矩阵。

output:

[[4 3 5]
[1 2 1]]
----
[[3 4 5]
[1 1 2]]
----
[2 3 1 0]
[1 2 3 4]

总结

整体来看numpy库已经包含了对矩阵的基本处理方式,有替代matlab的倾向。想比matlab,numpy库的优势还是很明显的。不过单纯学完numpy库,我还是没办法把它和程序化交易结合起来。不过学完这个库,以后就不用安装巨大的matlab 2012R 这个软件了。
NumPy 通常与 SciPy(Scientific Python)和 Matplotlib(绘图库)一起使用, 这种组合广泛用于替代 MatLab,是一个强大的科学计算环境,有助于我们通过 Python 学习数据科学或者机器学习。

参考资料

https://www.runoob.com/numpy/numpy-tutorial.html 菜鸟教程