目录

  • 为什么使用numpy
  • numpy矩阵的创建以及数据类型
    • 直接使用np.array创建
    • 使用numpy函数
      • np.arange()、np.linspace()
      • np.zeros() 、np.ones()、np.eye()
      • np.empty()、np.zeros_like()、np.ones_like()
      • 矩阵形状
      • 数据类型
  • numpy矩阵的计算
    • 广播原则
      • 数字计算
      • 矩阵计算
      • numpy中矩阵转置
  • numpy的切片、索引
  • numpy中的数字的寻找与替换
  • 矩阵的拼接
  • 矩阵的行列交换
  • 使用argmin与argmax获取矩阵中最大最小值
  • numpy生成随机数
    • 随机数种子
  • numpy中的nan与inf
    • nan与inf
    • 判断矩阵中有多少个nan
    • nan的替换
  • numpy中常用统计函数
  • numpy读取数据
  • 参考资料
import numpy as np

为什么使用numpy

numpy官方文档

  1. python自带list使用不方便,运行缓慢;
  2. numpy是python的计算拓展库,开源,集成了一系列已编译的数学和矩阵计算函数;
  3. numpy有独有的数据结构,使用方便,运行快速;
  4. numpy数据占用空间小,读取速度快。

numpy矩阵的创建以及数据类型

生成的类型为 numpy.ndarray,数据是线性的且连续存储。

直接使用np.array创建

a = np.array([1, 2, 3])

使用numpy函数

np.arange()、np.linspace()

''' np.arange([start,] stop[, step,], dtype = None) '''
>>> np.arange(1, 5)
array([1, 2, 3, 4])

''' numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0) 返回间隔均匀的数组 '''
# 生成了[0, 10]十一等分数据
>>> np.linspace(0, 10, 11)
array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10.])

np.zeros() 、np.ones()、np.eye()

>>> np.zeros((3, 4))
array([[0., 0., 0., 0.],
       [0., 0., 0., 0.],
       [0., 0., 0., 0.]])
>>> np.ones((3, 4))		
array([[1., 1., 1., 1.],
       [1., 1., 1., 1.],
       [1., 1., 1., 1.]])
 >>> np.eye(4)		# 对角矩阵
array([[1., 0., 0., 0.],
       [0., 1., 0., 0.],
       [0., 0., 1., 0.],
       [0., 0., 0., 1.]])    

np.empty()、np.zeros_like()、np.ones_like()

''' numpy.empty(shape, dtype=float, order='C') 返回shape形状的空矩阵 '''
>>> b = np.empty((3, 4))
>>> b
array([[6.89796323e-307, 2.78148153e-307, 2.78144588e-307,
        1.60219035e-306],
       [4.45064003e-308, 1.24611741e-306, 1.60219035e-306,
        4.22791195e-307],
       [3.44900369e-307, 4.00536722e-307, 2.33646845e-307,
        4.00540457e-307]])
        
''' numpy.zeros_like(a, dtype=None, order='K', subok=True, shape=None) 返回和a矩阵形状一样的零矩阵 '''
>>> np.zeros_like(b)	
array([[0., 0., 0., 0.],
       [0., 0., 0., 0.],
       [0., 0., 0., 0.]])
       
''' numpy.ones_like(a, dtype=None, order='K', subok=True, shape=None) 返回和a矩阵形状一样的1矩阵 '''
>>> np.ones_like(b)
array([[1., 1., 1., 1.],
       [1., 1., 1., 1.],
       [1., 1., 1., 1.]])

矩阵形状

numpy.shape,numpy.reshape()的运用。

# 矩阵的维度
>>> g = np.array([1, 2, 3], [4, 5, 6])
>>> g.shape		
(2, 3)

>>> h = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
array([[[ 1,  2,  3],
        [ 4,  5,  6]],

       [[ 7,  8,  9],
        [10, 11, 12]]])
        
>>> h.shape		
(2, 2, 3)

# 修改矩阵的形状, 注意矩阵中的元素个数是相同的,2 * 2 * 3 = 2 * 6
# 当不知道具体矩阵的维度时,可以通过shape来获取,h.shape[0], h.shape[1]
>>> h.reshape((2, 6))
array([[ 1,  2,  3,  4,  5,  6],
       [ 7,  8,  9, 10, 11, 12]])

>>> h
array([[[ 1,  2,  3],
        [ 4,  5,  6]],

       [[ 7,  8,  9],
        [10, 11, 12]]])
''' 注意reshape修改并未改变原来的矩阵,只是返回了一个新的值! '''

# 将一个多维数组按行展开
>>> h.flatten()
array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12])

数据类型

numpy 支持的数据类型比 Python 内置的类型要多很多,基本上可以和 C 语言的数据类型对应上。常用Numpy数据类型可见此。

使用dtype可以查看numpy数据的类型。

''' numpy.dtype(object, align, copy) object: 要转换为的数据类型对象 align: 如果为 true,填充字段使其类似 C 的结构体。 copy: 复制 dtype 对象, 如果为 false,则是对内置数据类型对象的引用 所输出的类型后的数字,若没有修改,代表的是该数据的默认位数, 默认指定的位数考虑到了效率与便捷问题,一般是比较通用的情况,可以自行修改 '''

>>> b = np.arange(1, 5)
>>> b.dtype
dtype('int32')	

>>> c = np.array(range(1, 6), dtype = float)
>>> c.dtype
dtype('float64')

>>> d = np.array(range(1, 6), dtype = "i1")
>>> d.dtype
dtype('int8')

''' 调整数据类型 '''
# eg: int8, int16, int32, int64 四种数据类型可以使用字符串 'i1', 'i2','i4','i8' 代替
>>> e = d.astype("int8")
>>> e.dtype
dtype('int8')

# 取小数操作
>>> f = np.array([random.random() for i in range(7)])
>>> np.round(f, 2)
array([0.73, 0.92, 0.33, 0.77, 0.67, 0.98, 0.48])

numpy矩阵的计算

广播原则

python的广播原则:
如果两个数组的后缘维度(trailing dimension),即从末尾开始算起的维度的轴长度相符或其中一方的长度为1则认为它们是广播兼容的。广播会在缺失和(或)长度为1的维度上进行。

eg: shape为(1, 2, 3)的矩阵

  1. 其可以和shape为(3)的矩阵计算,在第一维度和第二维度上进行;
  2. 其可和shape为(2, 3)的矩阵计算,在第一维度上进行;
  3. 其不可和shape为(2, 4)的矩阵计算。

具体编程示例如下:

数字计算

# python numpy计算的广播机制,整体变化
>>> i = np.arange(1, 13)
>>> i = i.reshape((3, 4))
>>> i
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12]])
>>> i + 3
array([[ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])
>>> i * 2
array([[ 2,  4,  6,  8],
       [10, 12, 14, 16],
       [18, 20, 22, 24]])
>>> j = i - 1
>>> j
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> j / 0
array([[nan, inf, inf, inf],
       [inf, inf, inf, inf],
       [inf, inf, inf, inf]])
''' 此时python提示warning,但是仍然可以计算,nan表示不是一个数字,inf表示无穷大 '''

矩阵计算

# 矩阵计算,注意维度问题
''' example 1 '''
>>> i + j
array([[ 1,  3,  5,  7],
[ 9, 11, 13, 15],
[17, 19, 21, 23]])
>>> i * j
array([[  0,   2,   6,  12],
[ 20,  30,  42,  56],
[ 72,  90, 110, 132]])
''' example 2-1 当其中某个为一维的时候,即这个维度不相等,此时也可计算, 但必须保证另一个维度相等 '''
>>> i
array([[ 1,  2,  3,  4],
[ 5,  6,  7,  8],
[ 9, 10, 11, 12]])
>>> k = np.arange(1, 5)
>>> k
array([1, 2, 3, 4])
>>> i * k		# 其中i形状为(3, 4), k为(1, 4), 满足广播原则
array([[ 1,  4,  9, 16],
[ 5, 12, 21, 32],
[ 9, 20, 33, 48]])   
>>> i + k
array([[ 2,  4,  6,  8],
[ 6,  8, 10, 12],
[10, 12, 14, 16]]) 
''' example 2-2 '''
>>> l = np.array([[1], [2], [3]])
>>> l
array([[1],
[2],
[3]])
>>> i + l		# i形状为(3, 4), l的形状为(3, 1), 长度为1, 满足广播机制
array([[ 2,  3,  4,  5],
[ 7,  8,  9, 10],
[12, 13, 14, 15]])
>>> i * l
array([[ 1,  2,  3,  4],
[10, 12, 14, 16],
[27, 30, 33, 36]])
''' example 3 '''
>>> a = np.arange(18).reshape(3, 3, 2)
>>> b = np.arange(9).reshape(3, 3)
>>> a
array([[[ 0,  1],
[ 2,  3],
[ 4,  5]],
[[ 6,  7],
[ 8,  9],
[10, 11]],
[[12, 13],
[14, 15],
[16, 17]]])
>>> b
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>> a + b
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: operands could not be broadcast together with shapes (3,3,2) (3,3)
''' 出现报错! 不满足广播机制,(3, 3, 2)与(3, 3)的矩阵不能够进行运算! '''
''' 当b修改为如下时(3, 3, 1)即可进行运算!(3, 3, 2)与(3, 3, 1) '''
>>> b = np.arange(9).reshape(3, 3, 1)
>>> b
array([[[0],
[1],
[2]],
[[3],
[4],
[5]],
[[6],
[7],
[8]]])
>>> a + b
array([[[ 0,  1],
[ 3,  4],
[ 6,  7]],
[[ 9, 10],
[12, 13],
[15, 16]],
[[18, 19],
[21, 22],
[24, 25]]])

numpy中矩阵转置

a = np.arange(12).reshape((3, 4))
# 法一:
a.transponse()
# 法二:
a.T
# 法三:交换轴
a.swapaxes(1, 0)

numpy的切片、索引

>>> a = np.arange(12).reshape((3, 4))
>>> a
array([[ 0,  1,  2,  3],
[ 4,  5,  6,  7],
[ 8,  9, 10, 11]])
>>> a[1:3]		# 取行
array([[ 4,  5,  6,  7],
[ 8,  9, 10, 11]])
>>> a[:, 2:4]	# 取列
array([[ 2,  3],
[ 6,  7],
[10, 11]])
>>> a[[0, 2]]		# 不连续的多行
array([[ 0,  1,  2,  3],
[ 8,  9, 10, 11]])
>>> a[[0, 2], [1, 3]]	# 多个点
array([ 1, 11])
''' 注意虽然取的是整数,但是并不是之前的int32类型 '''
>>> type(a[1, 2])
<class 'numpy.int32'>

numpy中的数字的寻找与替换

>>> a = np.arange(12).reshape((3, 4))
>>> a
array([[ 0,  1,  2,  3],
[ 4,  5,  6,  7],
[ 8,  9, 10, 11]])
>>> a < 5
array([[ True,  True,  True,  True],
[ True, False, False, False],
[False, False, False, False]])
''' 法一:使用逻辑判断True和False,将a矩阵中所有小于5的数替换为6 '''
>>> a[a < 5] = 6
>>> a
array([[ 6,  6,  6,  6],
[ 6,  5,  6,  7],
[ 8,  9, 10, 11]])
>>> a = np.arange(12).reshape((3, 4))
>>> a[a < 5]	# 注意区分这个和上面赋值
array([0, 1, 2, 3, 4])
''' 法二:使用where函数 numpy.where(condition[, x, y]) 根据条件返回从x或y中选择的元素 '''
# 将矩阵a中所有小于5的数替换为6,大于5的数替换为1
>>> np.where(a < 5, 6, 1)
array([[6, 6, 6, 6],
[6, 1, 1, 1],
[1, 1, 1, 1]])
''' 法三:使用clip函数 numpy.clip(a, a_min, a_max, out=None, **kwargs) 给定一个区间,区间外的值被裁剪到区间的边界上, 举例来说,给定区间[a, b],大于b的变成b,小于a的变成a '''
# numpy中的clip,大于8的变为8,小于5的变成5
>>> a.clip(5, 8)
array([[5, 5, 5, 5],
[5, 5, 6, 7],
[8, 8, 8, 8]])
''' numpy矩阵含有inf、nan的类型转换 '''
>>> a[2, 3] = np.nan
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: cannot convert float NaN to integer
# 需要对numpy矩阵类型进行转换,如下即可
>>> a = a.astype(float)
>>> a
array([[ 0.,  1.,  2.,  3.],
[ 4.,  5.,  6.,  7.],
[ 8.,  9., 10., 11.]])
>>> a[2, 3] = np.nan
>>> a
array([[ 0.,  1.,  2.,  3.],
[ 4.,  5.,  6.,  7.],
[ 8.,  9., 10., nan]])

矩阵的拼接

>>> a = np.arange(12).reshape((3, 4))
>>> a
array([[ 0,  1,  2,  3],
[ 4,  5,  6,  7],
[ 8,  9, 10, 11]])
>>> b = np.arange(12, 24).reshape((3, 4))
>>> b
array([[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]])
''' 竖直拼接,注意竖直分割是这个方向 '''
>>> np.vstack((a, 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]])
''' 水平拼接,注意水平分割是这个方向 '''
>>> np.hstack((a, b))
array([[ 0,  1,  2,  3, 12, 13, 14, 15],
[ 4,  5,  6,  7, 16, 17, 18, 19],
[ 8,  9, 10, 11, 20, 21, 22, 23]])    

矩阵的行列交换

>>> a = np.arange(12).reshape((3, 4))
>>> a
array([[ 0,  1,  2,  3],
[ 4,  5,  6,  7],
[ 8,  9, 10, 11]])
# 行交换
>>> a[[0, 1], :] = a[[1, 0], :]
>>> a
array([[ 4,  5,  6,  7],
[ 0,  1,  2,  3],
[ 8,  9, 10, 11]])
# 列交换
>>> a[:, [0, 1]] = a[:, [1, 0]]
>>> a
array([[ 5,  4,  6,  7],
[ 1,  0,  2,  3],
[ 9,  8, 10, 11]])

使用argmin与argmax获取矩阵中最大最小值

>>> c = np.array([random.randint(1, 100) for i in range(12)]).reshape((3, 4))
>>> c
array([[ 66, 100,  19,  48],
[ 95,  68,  81,   9],
[ 60,  80,  12,  63]])
''' 获取最大值位置 '''
>>> np.argmax(c)	# 相当于数组为一维的时索引
1
>>> np.argmax(c, axis = 0)		# 取的为每一列的最大值
array([1, 0, 1, 2], dtype=int64)
''' 获取最小值位置 '''
>>> np.argmin(c)	# 相当于数组为一维的时索引
7
>>> np.argmin(c, axis = 1)		# 取得为每一行的最小值
array([2, 3, 2], dtype=int64)

numpy生成随机数

参数 说明
.rand(d0, d1, …, dn) 创建d0—dn维度的均匀分布的随机数数组,范围为[0, 1),浮点数
.randn(d0, d1, …, dn) 创建d0—dn维度、满足均值为0、方差为1的标准正态分布随机数数组,未给定参数的情况下,返回从分布中随机采样的单个浮点数
.randint(low, high=None, size=None, dtype=int) 从指定dtype的离散均匀分布[low, high)中返回随机整数,如果没有指定high,默认区间为[0, low)
.uniform(low=0.0, high=1.0, size=None) 样本均匀分布在区间[low, high),从其中抽取样本
.normal(loc=0.0, scale=1.0, size=None) 从正态分布中抽取随机样本,loc为均值,scale为标准差
.seed(self, seed=None) 随机数种子,seed是给定的种子值,通过设定相同的随机数种子,可以每次生成相同的随机数(计算机生成的是伪随机数)
>>> np.random.rand(3,4)
array([[0.6350389 , 0.42583308, 0.83244198, 0.13534336],
[0.1646268 , 0.08109012, 0.31921804, 0.58858143],
[0.16737554, 0.22531111, 0.89541298, 0.35630342]])

随机数种子

import numpy as np
i = 0
while i < 5:
np.random.seed(3)
print(np.random.rand(1, 2))
i = i + 1

上述代码输出为:

[[0.5507979  0.70814782]]
[[0.5507979  0.70814782]]
[[0.5507979  0.70814782]]
[[0.5507979  0.70814782]]
[[0.5507979  0.70814782]]

对代码修改如下:

import numpy as np
i = 0
np.random.seed(3)
while i < 5:
print(np.random.rand(1, 2))
i = i + 1

输出为:

[[0.5507979  0.70814782]]
[[0.29090474 0.51082761]]
[[0.89294695 0.89629309]]
[[0.12558531 0.20724288]]
[[0.0514672  0.44080984]]

两者的区别在于随机数种子的设置位置不同,随机数种子设置一定的时候,产生的随机数一样,但后者是将随机数种子的设置放到了循环之外,使得除第一次循环之外,其余的军事重新生成的随机数种子,于是生成的每次结果均不相同。

numpy中的nan与inf

nan与inf

nan(not a number):表示并非一个数字,它和任何值计算的结果都是nan,典型出现情况如下:

  1. 当计算不恰当时(如0/0,且结果不为inf/-inf),则会出现nan;
  2. 当读取本地float文件出现缺失时
    inf(infinity / – infinity):无穷大(正负),出现典型情况是非0的数a除以0,其出现在python中会直接报错,如下:
>>> 1/0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero

注意 np,inf 与 np.nan 均为float类型

# 两个np.nan不相等
>>> np.nan == np.nan
False

判断矩阵中有多少个nan

''' 法一:可以利用numpy中count_nonzero函数来判断矩阵中有几个nan numpy.count_nonzero(a, axis=None, *, keepdims=False) 对数组a中的非零值进行计数 '''
>>> a
array([[ 5.,  4.,  6.,  7.],
[ 1.,  0., nan,  3.],
[ 9., nan, 10., 11.]])
>>> a != a
array([[False, False, False, False],
[False, False,  True, False],
[False,  True, False, False]])
>>> np.count_nonzero(a != a)
2
''' 法二:利用np.isnan()函数 numpy.isnan(x, /, out=None, *, where=True, casting='same_kind', order='K', dtype=None, subok=True[, signature, extobj]) = <ufunc 'isnan'> 测试数组中是否有元素nan,并以布尔数组的形式返回结果 '''
>>> np.isnan(a)
array([[False, False, False, False],
[False, False,  True, False],
[False,  True, False, False]])
>>> np.count_nonzero(np.isnan(a))
2
''' nan和任何值作计算,结果均为nan '''
>>> a
array([[ 5.,  4.,  6.,  7.],
[ 1.,  0., nan,  3.],
[ 9., nan, 10., 11.]])
>>> np.sum(a)
nan
>>> np.sum(a, axis = 0)
array([15., nan, nan, 21.])
>>> np.sum(a, axis = 1)
array([22., nan, nan])

nan的替换

nan在读取数据中通常是缺失值,一般把nan替换为均值,或者是直接删除有nan的那一行/列。

numpy中常用统计函数

函数 功能
np.sum(a) 、a.sum() 求和
np.mean(a)、a.mean() 均值
np.median(a) 中值
np.max(a)、a.max() 最大值
np.min(a)、a.min() 最小值
np.ptp(a)、a.ptp() 极值
np.std(a)、a.std() 标准差

numpy读取数据

分析数据的思路:看到这个问题,我们应该怎么思考?

  1. 想要得出什么结论,解决什么问题?
  2. 选择什么样的呈现方式?
  3. 数据还需要做什么样的处理?
  4. 编写代码

numpy.loadtxt的说明文档

numpy.loadtxt(fname, dtype=<class 'float'>, comments='#', delimiter=None, converters=None, skiprows=0, usecols=None, unpack=False, ndmin=0, encoding='bytes', max_rows=None)

参数含义如下:

参数 解释
frame 需要读取的文件
dtype 读取数组的数据类型,默认为浮点数
comments 用来表示注释开始的字符,默认为#
delimiter 用于分隔值的字符串,默认为空格
skiprows 跳过几行开始读数,包括注释
usecols 要读取的列,第一列为0,默认值为None,读取所有
unpack 如果为True,返回的数组将会被转置,便于将属性分别写入不同的数组变量,默认为False,仅仅写入一个数组变量
ndmin 返回的数组至少有ndmin维度,否则,一维轴将被压缩,值可取0(默认值),1,2
encoding 用于解码输入文件的编码,默认为bytes
max_rows 从跳过行数之后开始,读取的最多行数,默认情况下读取所有行

(等有时间可以整理更完善些。)

参考资料

  1. https://numpy.org/doc/stable/reference/generated/numpy.isnan.html?highlight=isnan#numpy.isnan
  2. https://stackoverflow.com/questions/41774047/using-numpy-to-square-value-gives-negative-number
  3. https://www.runoob.com/numpy/numpy-dtype.html
  4. 视频教程

本文地址:https://blog.csdn.net/TXY_xy/article/details/111055369