欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python数据科学库numpy如何使用

程序员文章站 2022-03-22 15:38:10
目录numpy创建矩阵import numpy as npnumpy创建矩阵# 生成的类型为 numpy.ndarraya = np.array([1, 2, 3])# np.arange([start,] stop[, step,], dtype = None)b = np.arange(1, 5)print(b.dtype)# 输出为int64,指的是numpy中的数据类型,没有指定类型时,后面跟的数字是电脑的位数c = np.array(range(1, 6), dtype...

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://*.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

相关标签: python numpy