回炉重造python之numpy详细教程(2万字总结)(代码片段)

ZSYL ZSYL     2023-01-04     570

关键词:

Python之numpy详细教程

前言

Numpy(Numerical Python的简称)是一个专门用来做科学计算的库,主要用在多维数组(矩阵)方面的处理。

因为Numpy底层是用C语言开发的,所以他在处理一些多维数组(矩阵)的时候,比原生Python的列表快得很多。

Numpy是个基础的科学计算库,Python其余的科学计算扩展大部分都是以此为基础。

安装:

进入到你自己的环境中,然后输入conda install numpy即可安装。安装完成后,以后在pycharm中使用的时候如果出现以下错误:

那么需要把Anaconda的安装路径添加到PATH的环境变量中。比如我是把Anaconda安装在D:\\ProgramApp\\Anaconda,那么需要添加以下三个环境变量:

Numpy库介绍

NumPy是一个功能强大的Python库,主要用于对多维数组执行计算。

NumPy这个词来源于两个单词-- NumericalPythonNumPy提供了大量的库函数和操作,可以帮助程序员轻松地进行数值计算。在数据分析和机器学习领域被广泛使用。他有以下几个特点:

  1. numpy内置了并行运算功能,当系统有多个核心时,做某种计算时,numpy会自动做并行计算。
  2. Numpy底层使用C语言编写,内部解除了GIL(全局解释器锁),其对数组的操作速度不受Python解释器的限制,效率远高于纯Python代码。
  3. 有一个强大的N维数组对象Array(一种类似于列表的东西)。
  4. 实用的线性代数、傅里叶变换和随机数生成函数。

总而言之,他是一个非常高效的用于处理数值型运算的包。

安装:

通过pip install numpy即可安装。

教程地址:

  1. 官网:https://docs.scipy.org/doc/numpy/user/quickstart.html
  2. 中文文档:https://www.numpy.org.cn/user_guide/quickstart_tutorial/index.html

Numpy数组和Python列表性能对比:

比如我们想要对一个Numpy数组和Python列表中的每个素进行求平方。那么代码如下:

# Python列表的方式
t1 = time.time()
a = []
for x in range(100000):
    a.append(x**2)
t2 = time.time()
t = t2 - t1
print(t)

花费的时间大约是0.07180左右。而如果使用numpy的数组来做,那速度就要快很多了:

t3 = time.time()
b = np.arange(100000)**2
t4 = time.time()
print(t4-t3)

NumPy数组基本用法

  1. NumpyPython科学计算库,用于快速处理任意维度的数组。
  2. NumPy提供一个N维数组类型ndarray,它描述了相同类型的“items”的集合。
  3. numpy.ndarray支持向量化运算。
  4. NumPy使用c语言写的,底部解除了GIL,其对数组的操作速度不在受python解释器限制。

numpy中的数组:

Numpy中的数组的使用跟Python中的列表非常类似。他们之间的区别如下:

  1. 一个列表中可以存储多种数据类型。比如a = [1,'a']是允许的,而数组只能存储同种数据类型。
  2. 数组可以是多维的,当多维数组中所有的数据都是数值类型的时候,相当于线性代数中的矩阵,是可以进行相互间的运算的。

创建数组(np.ndarray对象):

Numpy经常和数组打交道,因此首先第一步是要学会创建数组。在Numpy中的数组的数据类型叫做ndarray。以下是两种创建的方式:

  1. 根据Python中的列表生成:

    import numpy as np
    a1 = np.array([1,2,3,4])
    print(a1)
    print(type(a1))
    
  2. 使用np.arange生成,np.arange的用法类似于Python中的range

    import numpy as np
    a2 = np.arange(2,21,2)
    print(a2)
    
  3. 使用np.random生成随机数的数组:

    a1 = np.random.random(2,2) # 生成2行2列的随机数的数组
    a2 = np.random.randint(0,10,size=(3,3)) # 元素是从0-10之间随机的3行3列的数组
    
  4. 使用函数生成特殊的数组:

    import numpy as np
    a1 = np.zeros((2,2)) #生成一个所有元素都是0的2行2列的数组
    a2 = np.ones((3,2)) #生成一个所有元素都是1的3行2列的数组
    a3 = np.full((2,2),8) #生成一个所有元素都是8的2行2列的数组
    a4 = np.eye(3) #生成一个在斜方形上元素为1,其他元素都为0的3x3的矩阵
    

ndarray常用属性:

ndarray.dtype

因为数组中只能存储同一种数据类型,因此可以通过dtype获取数组中的元素的数据类型。以下是ndarray.dtype的常用的数据类型:

数据类型描述唯一标识符
bool用一个字节存储的布尔类型(True或False)‘b’
int8一个字节大小,-128 至 127‘i1’
int16整数,16 位整数(-32768 ~ 32767)‘i2’
int32整数,32 位整数(-2147483648 ~ 2147483647)‘i4’
int64整数,64 位整数(-9223372036854775808 ~ 9223372036854775807)‘i8’
uint8无符号整数,0 至 255‘u1’
uint16无符号整数,0 至 65535‘u2’
uint32无符号整数,0 至 2 ** 32 - 1‘u4’
uint64无符号整数,0 至 2 ** 64 - 1‘u8’
float16半精度浮点数:16位,正负号1位,指数5位,精度10位‘f2’
float32单精度浮点数:32位,正负号1位,指数8位,精度23位‘f4’
float64双精度浮点数:64位,正负号1位,指数11位,精度52位‘f8’
complex64复数,分别用两个32位浮点数表示实部和虚部‘c8’
complex128复数,分别用两个64位浮点数表示实部和虚部‘c16’
object_python对象‘O’
string_字符串‘S’
unicode_unicode类型‘U’

我们可以看到,Numpy中关于数值的类型比Python内置的多得多,这是因为Numpy为了能高效处理处理海量数据而设计的。举个例子,比如现在想要存储上百亿的数字,并且这些数字都不超过254(一个字节内),我们就可以将dtype设置为int8,这样就比默认使用int64更能节省内存空间了。类型相关的操作如下:

  1. 默认的数据类型:

    import numpy as np
    a1 = np.array([1,2,3])
    print(a1.dtype) 
    # 如果是windows系统,默认是int32
    # 如果是mac或者linux系统,则根据系统来
    
  2. 指定dtype

    import numpy as np
    a1 = np.array([1,2,3],dtype=np.int64)
    # 或者 a1 = np.array([1,2,3],dtype="i8")
    print(a1.dtype)
    
  3. 修改dtype

    import numpy as np
    a1 = np.array([1,2,3])
    print(a1.dtype) # window系统下默认是int32
    # 以下修改dtype
    a2 = a1.astype(np.int64) # astype不会修改数组本身,而是会将修改后的结果返回
    print(a2.dtype)
    

ndarray.size

获取数组中总的元素的个数。比如有个二维数组:

   import numpy as np
   a1 = np.array([[1,2,3],[4,5,6]])
   print(a1.size) #打印的是6,因为总共有6个元素

ndarray.ndim

数组的维数。比如:

   a1 = np.array([1,2,3])   print(a1.ndim) # 维度为1   a2 = np.array([[1,2,3],[4,5,6]])   print(a2.ndim) # 维度为2   a3 = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])   print(a3.ndim) # 维度为3

ndarray.shape

数组的维度的元组。比如以下代码:

   a1 = np.array([1,2,3])   print(a1.shape) # 输出(3,),意思是一维数组,有3个数据   a2 = np.array([[1,2,3],[4,5,6]])   print(a2.shape) # 输出(2,3),意思是二位数组,2行3列   a3 = np.array([       [           [1,2,3],           [4,5,6]       ],       [           [7,8,9],           [10,11,12]       ]   ])   print(a3.shape) # 输出(2,2,3),意思是三维数组,总共有2个元素,每个元素是2行3列的   a44 = np.array([1,2,3],[4,5])   print(a4.shape) # 输出(2,),意思是a4是一个一维数组,总共有2列   print(a4) # 输出[list([1, 2, 3]) list([4, 5])],其中最外面层是数组,里面是Python列表

另外,我们还可以通过ndarray.reshape来重新修改数组的维数。示例代码如下:

   a1 = np.arange(12) #生成一个有12个数据的一维数组   print(a1)    a2 = a1.reshape((3,4)) #变成一个2维数组,是3行4列的   print(a2)   a3 = a1.reshape((2,3,2)) #变成一个3维数组,总共有2块,每一块是2行2列的   print(a3)   a4 = a2.reshape((12,)) # 将a2的二维数组重新变成一个12列的1维数组   print(a4)   a5 = a2.flatten() # 不管a2是几维数组,都将他变成一个一维数组   print(a5)

注意,reshape并不会修改原来数组本身,而是会将修改后的结果返回。如果想要直接修改数组本身,那么可以使用resize来替代reshape

ndarray.itemsize

数组中每个元素占的大小,单位是字节。比如以下代码:

   a1 = np.array([1,2,3],dtype=np.int32)   print(a1.itemsize) # 打印4,因为每个字节是8位,32位/8=4个字节

Numpy数组操作

数组广播机制:

数组与数的计算:

Python列表中,想要对列表中所有的元素都加一个数,要么采用map函数,要么循环整个列表进行操作。但是NumPy中的数组可以直接在数组上进行操作。

示例代码如下:

import numpy as np
a1 = np.random.random((3,4))
print(a1)
# 如果想要在a1数组上所有元素都乘以10,那么可以通过以下来实现
a2 = a1*10
print(a2)
# 也可以使用round让所有的元素只保留2位小数
a3 = a2.round(2)

以上例子是相乘,其实相加、相减、相除也都是类似的。

数组与数组的计算:

  1. 结构相同的数组之间的运算:

    a1 = np.arange(0,24).reshape((3,8))
    a2 = np.random.randint(1,10,size=(3,8))
    a3 = a1 + a2 #相减/相除/相乘都是可以的
    print(a1)
    print(a2)
    print(a3)
    
  2. 与行数相同并且只有1列的数组之间的运算:

    a1 = np.random.randint(10,20,size=(3,8)) #3行8列
    a2 = np.random.randint(1,10,size=(3,1)) #3行1列
    a3 = a1 - a2 #行数相同,且a2只有1列,能互相运算
    print(a3)
    
  3. 与列数相同并且只有1行的数组之间的运算:

    a1 = np.random.randint(10,20,size=(3,8)) #3行8列
    a2 = np.random.randint(1,10,size=(1,8))
    a3 = a1 - a2
    print(a3)
    

广播原则:

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

看以下案例分析:

  1. shape(3,8,2)的数组能和(8,3)的数组进行运算吗?
    分析:不能,因为按照广播原则,从后面往前面数,(3,8,2)(8,3)中的23不相等,所以不能进行运算。

  2. shape(3,8,2)的数组能和(8,1)的数组进行运算吗?
    分析:能,因为按照广播原则,从后面往前面数,(3,8,2)(8,1)中的21虽然不相等,但是因为有一方的长度为1,所以能参与运算。

  3. shape(3,1,8)的数组能和(8,1)的数组进行运算吗?
    分析:能,因为按照广播原则,从后面往前面数,(3,1,4)(8,1)中的41虽然不相等且18不相等,但是因为这两项中有一方的长度为1,所以能参与运算。


数组形状的操作:

可以通过一些函数,非常方便的操作数组的形状。

reshape和resize方法:

两个方法都是用来修改数组形状的,但是有一些不同。

  1. reshape是将数组转换成指定的形状,然后返回转换后的结果,对于原数组的形状是不会发生改变的。调用方式:

    a1 = np.random.randint(0,10,size=(3,4))
    a2 = a1.reshape((2,6)) #将修改后的结果返回,不会影响原数组本身
    
  2. resize是将数组转换成指定的形状,会直接修改数组本身。并不会返回任何值。调用方式:

    a1 = np.random.randint(0,10,size=(3,4))
    a1.resize((2,6)) #a1本身发生了改变
    

flatten和ravel方法:

两个方法都是将多维数组转换为一维数组,但是有以下不同:

  1. flatten是将数组转换为一维数组后,然后将这个拷贝返回回去,所以后续对这个返回值进行修改不会影响之前的数组。
  2. ravel是将数组转换为一维数组后,将这个视图(可以理解为引用)返回回去,所以后续对这个返回值进行修改会影响之前的数组。
    比如以下代码:
x = np.array([[1, 2], [3, 4]])
x.flatten()[1] = 100 #此时的x[0]的位置元素还是1
x.ravel()[1] = 100 #此时x[0]的位置元素是100

不同数组的组合:

如果有多个数组想要组合在一起,也可以通过其中的一些函数来实现。

  1. vstack:将数组按垂直方向进行叠加。数组的列数必须相同才能叠加。示例代码如下:

    a1 = np.random.randint(0,10,size=(3,5))
    a2 = np.random.randint(0,10,size=(1,5))
    a3 = np.vstack([a1,a2])
    
  2. hstack:将数组按水平方向进行叠加。数组的行必须相同才能叠加。示例代码如下:

    a1 = np.random.randint(0,10,size=(3,2))
    a2 = np.random.randint(0,10,size=(3,1))a3 = np.hstack([a1,a2])
    
  3. concatenate([],axis):将两个数组进行叠加,但是具体是按水平方向还是按垂直方向。则要看axis的参数,如果axis=0,那么代表的是往垂直方向(行)叠加,如果axis=1,那么代表的是往水平方向(列)上叠加,如果axis=None,那么会将两个数组组合成一个一维数组。
    需要注意的是,如果往水平方向上叠加,那么行必须相同,如果是往垂直方向叠加,那么列必须相同。

示例代码如下:

a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6]])
np.concatenate((a, b), axis=0)
# 结果:
array([[1, 2],
    [3, 4],
    [5, 6]])

np.concatenate((a, b.T), axis=1)
# 结果:
array([[1, 2, 5],
    [3, 4, 6]])

np.concatenate((a, b), axis=None)
# 结果:
array([1, 2, 3, 4, 5, 6])

数组的切割:

通过hsplitvsplit以及array_split可以将一个数组进行切割。

  1. hsplit:按照水平方向进行切割。用于指定分割成几列,可以使用数字来代表分成几部分,也可以使用数组来代表分割的地方。

示例代码如下:

a1 = np.arange(16.0).reshape(4, 4)
np.hsplit(a1,2) #分割成两部分
>>> array([[ 0.,  1.],
     [ 4.,  5.],
     [ 8.,  9.],
     [12., 13.]]), array([[ 2.,  3.],
     [ 6.,  7.],
     [10., 11.],
     [14., 15.]])]

np.hsplit(a1,[1,2]) #代表在下标为1的地方切一刀,下标为2的地方切一刀,分成三部分
>>> [array([[ 0.],
     [ 4.],
     [ 8.],
     [12.]]), array([[ 1.],
     [ 5.],
     [ 9.],
     [13.]]), array([[ 2.,  3.],
     [ 6.,  7.],
     [10., 11.],
     [14., 15.]])]
  1. vsplit:按照垂直方向进行切割。用于指定分割成几行,可以使用数字来代表分成几部分,也可以使用数组来代表分割的地方。示例代码如下:
np.vsplit(x,2) #代表按照行总共分成2个数组
>>> [array([[0., 1., 2., 3.],
     [4., 5., 6., 7.]]), array([[ 8.,  9., 10., 11.],
     [12., 13., 14., 15.]])]

np.vsplit(x,(1,2)) #代表按照行进行划分,在下标为1的地方和下标为2的地方分割
>>> [array([[0., 1., 2., 3.]]),
    array([[4., 5宝藏级全网最全的pandas详细教程(2万字总结)(代码片段)

【回炉重造】Python之Pandas详细教程前言为什么要学习Pandas?什么是Pandas?1.Pandas的索引操作1.Series和DataFrame中的索引都是Index对象2.索引对象不可变,保证了数据的安全3.常见的Index种类3.1Series索引1.index指定行索引名2.行索引3.切片... 查看详情

jdbc万字长文总结回炉重造(代码片段)

JDBC-万字长文总结1.概述1.1什么是JDBC1.2JDBCAPI1.3JDBC可以做什么1.4JDBC程序编写步骤2.演示完整步骤2.1引入JDBC驱动程序2.2加载并注册驱动2.2.1Class.forName()2.2.2服务提供者框架2.3获取数据库链接2.4操作或访问数据库2.4.1Statement2.4.2ResultSet2.... 查看详情

强烈推荐一文带你搞定python基础篇(回炉重造)(代码片段)

Python基础篇1.变量2.命名习惯3.格式化输出3.1格式化符号3.2体验3.3转义字符3.4结束符4.转换数据类型5.数据类型5.1字符串5.2列表5.3元组5.4字典5.5集合6.公共操作6.1公共方法7.推导式7.1列表推导式1.1快速体验1.2带if的列表推导式1.3多个fo... 查看详情

回炉重造之重读windows核心编程-026-窗口消息(代码片段)

26窗口消息本章介绍Microsoft的消息系统是如何支持带有图形界面的应用程序的。首先设计Win2K以后的消息系统时,有两个主要目标:尽可能保持与过去16位Windows兼容,偏于移植现有的16位Windows程序。使窗口系统强壮,一个线程不... 查看详情

回炉重造之重读windows核心编程-014-虚拟内存(代码片段)

14.1系统信息GetSystemInfo函数用户检索与主机相关的值,只需要传递SYSTEM_INFO结构体的地址即可。typedefstruct_SYSTEM_INFOunionDWORDdwOemId;structWORDwProcessorArchiteture;WORDwReserved;;;DWORDdwPageSize;LPVOIDlpMinimumApplicationAddress;LPVOIDlpMaximumApplicationAddressDW... 查看详情

vue回炉重造之router路由

安装vue-routernpmivue-router-S1配置1、创建文件夹与文件创建一个router文件夹,在文件夹中创建两个文件,分别是router.js和routes.js文件。2、编辑文件router.js(路由配置文件)importRouterfrom‘vue-router‘importroutesfrom‘./routes‘exportdefault()=&... 查看详情

回炉重造jquery入门教程(代码片段)

jQuery的介绍学习目标能够知道JQuery的作用及优点1.jQuery的定义jQuery是对JavaScript的封装,它是免费、开源的JavaScript函数库,jQuery极大地简化了JavaScript编程。2.jQuery的作用jQuery和JavaScript它们的作用一样,都是负责网页行... 查看详情

回炉重造mysql基础知识(代码片段)

MySQL知识总结学习目标1.数据库的好处2.数据库相关概念3.数据库存储数据的特点3.MySQL产品的介绍和安装3.1MySQL服务的启动和停止3.2MySQL服务的登录和退出3.3MySQL的常见命令3.4MySQL的语法规范4.SQL的语言分类4.1SQL的常见命令4.2DQL语言... 查看详情

javascript回炉重造(代码片段)

【JavaScript】回炉重造(三)循环语句1.循环语句的介绍2.for循环3.while循环4.do-while循环5.小结字符串拼接1.字符串拼接小结定时器1.定时器的介绍2.定时器的使用:3.清除定时器4.小结循环语句学习目标能够写出2种循环语... 查看详情

机器学习线性回归(回炉重造)(代码片段)

机器学习---线性回归1.简单线性回归2.多元线性回归3.线性回归的正规方程解4.衡量线性回归的性能指标MSERMSEMAER-Squared5.scikit-learn线性回归实践-波斯顿房价预测LinearRegression线性回归是属于机器学习里面的监督学习,与分类问题... 查看详情

javascript回炉重造(代码片段)

【回炉重造】JavaScript函数定义和调用1.函数定义2.函数调用3.定义有参数有返回值的函数4.小结变量作用域1.变量作用域的介绍2.局部变量3.全局变量4.小结条件语句1.条件语句的介绍2.条件语句语法3.比较运算符4.逻辑运算符5.小结函... 查看详情

回炉重造之重读windows核心编程-001-错误处理

  Windows处理错误靠的是API的返回值,类型不止一种种:VOID,函数不可能失败,WindowsAPI的返回值很少是这个情况。BOOL,如果函数失败,则返回值是0,否则返回是非零值。不要测试返回值是否为TRUE!HANDLE,如果函数失败,则返... 查看详情

爬虫进阶爬虫概述基础篇(回炉重造)

爬虫概述爬虫概要1.爬虫的概念2.爬虫的作用3.爬虫的分类3.1根据被爬取网站的数量不同,可以分为:3.2根据是否以获取数据为目的,可以分为:3.3根据url地址和对应的页面内容是否改变,数据增量爬虫可以分... 查看详情

javascript回炉重造(代码片段)

【JavaScript】回炉重造(二)获取标签元素1.获取标签元素2.小结操作标签元素属性1.属性的操作2.innerHTML3.小结数组及操作方法1.数组的介绍2.数组的定义3.多维数组4.数组的操作5.小结获取标签元素学习目标能够写出获取标... 查看详情

回炉重造之重读windows核心编程-003-内核对象

  内核对象是个比较难理解的概念,问题的根源就在于即使是《核心编程》书中也没有说清楚它的定义,只是不停地举例和描述它的性质,还有如何使用。  盲人摸象,难见全貌。只能尽可能列举它的性质,注意使用了。 ... 查看详情

回炉重造之重读windows核心编程-006-线程

  线程也是有两部分组成的:线程的内核对象,操作系统用来管理线程和统计线程信息的地方。线程堆栈,用于维护现场在执行代码的时候用到的所有函数参数和局部变量。  进程是线程的容器,如果进程中有一个以上的线... 查看详情

回炉重造带你搞懂什么是机器学习?(代码片段)

带你搞懂什么是机器学习?机器学习介绍什么是机器学习:机器学习应用案例:机器学习程序开发流程:1.获取数据:2.清洗数据:3.训练模型:4.测试模型:5.投入使用:开发环境:Scikit-Learn... 查看详情

回炉重造带你搞懂什么是机器学习?(代码片段)

带你搞懂什么是机器学习?机器学习介绍什么是机器学习:机器学习应用案例:机器学习程序开发流程:1.获取数据:2.清洗数据:3.训练模型:4.测试模型:5.投入使用:开发环境:Scikit-Learn... 查看详情