Numpy基础笔记
Basic Numpy
ndarray对象基础
什么是ndarray对象?即是N-dimentional array,也就是n维数组对象。
指定ndarray类型的对象——dtype(data type,就是n维数组对象内的基本元素类型)
numpy数组的基本知识
数组的基本属性
- shape属性,即是数组的形状,用元组来描述(储存着几行几列的信息)
- axis属性,即是数组的轴,有0、1、2……轴(在参数列表中的axis代表着以哪个轴作为基准)
- ndim属性,即是数组的维数,用元组来表示(其实就是反映数组有几个轴)
- size属性,返回数组的长度(就是看数组里面一共有多少基本元素,不要与len()函数返回值混淆,len与ndim返回值一致)
- dtype属性,即是数组元素的类型(也可以在外面直接创造复杂dtype类型,并把它与一个变量绑定,可以节省代码量)
- itemsize属性,即是数组中每个元素的长度(以字节形式表示)
数据类型(主要在结构化数组中应用)
全部数据类型
见 Python Data Analysis P34,不过一般很少使用
结构化数组中的数据类型
bytes | b1 |
---|---|
int | i1, i2, i4, i8 |
usigned ints | u1, u2, u4, u8 |
floats | f2, f4, f8 |
complex | c8, c16 |
fixed length strings | a |
可以通过type函数来查看元素类型或查看ndarray的dtype属性
创建数组(包含特殊数组创建)
-
arr = np.array([1, 2, 3]) //array接收序列参数,通常用list, tuple(且他们地位等价,即互相嵌套可以换位)
-
np.arange(1, 100, 2) //arange在给定范围内生成一个一维数组,为闭开区间,为比较常用的方法。 //接收一个参数时默认从0开始,数字型参数-初始,结束,步长(步长可以为小数,与range不同,这十分特殊!!!!!) // 记住reshape函数!!!即可接收元组也可直接接受元组内的参数,通常使用 c = np.arange(0, 16).reshape((4, 4)) //reshape方法可以返回一个按参数指定形状的多维数组 np.arange(0, 16).resize((4, 4)) //resize方法与reshape方法的不同之处在于resize直接修改原对象,但是resize并不常用,我们希望对象更安全 //但是reshape产生的新视图,其实是一个引用,即使两者形状不一样,但是他们指向内存的同一块区域,如果要更改其中之一,请使用copy函数来避免这种事情发生
-
arr = np.linspace(0, 10, 5) //linspace函数接收:起始,结束,份数。它与arange相对应,只不过第三个参数从步长变为了份数 //其余像与shape, reshape方法的配合与arange一直(本质是对对象应用,只不过它们通常成对出现) // 其实linspace与arange是一样的,只不过使用的方式略有区别而已 // linspace中的重要参数,restep(导致linspace返回一个元组,前半部分是生成的array,后部分是步长),linspace与arange的不同之处在于 linspace默认包括右端而arange并不是,可以通过将endpoint设置为False,就可不取右端点
-
//快速创建特殊数组 // 注意!zeros、ones、random只能接收元组类参数!注意与reshape、shape区别! // 零数组 np.zeros((3, 3)) array([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]]) //zeros_like函数!跟ones_like一模一样 //一数组 np.ones((3, 3)) array([[1., 1., 1.], [1., 1., 1.], [1., 1., 1.]]) arr = np.array([1, 2, 3]) // one_like函数!可以根据已有数组的形状创建一数组 np.ones_like(arr) //随机数组 np.random.random((3, 3)) array([[0.23159009, 0.63306642, 0.63343724], [0.2765953 , 0.57742195, 0.3329211 ], [0.02730095, 0.86618645, 0.98329664]]) // 创建一个空数组(随机分配的垃圾值) np.empty((2, 3)) np.empty_like(arr) // 最一般的特殊数组创建函数!full函数 np.full(((2, 3), 7.1)) // 创建一个2x3的7.1充满的数组 np.full_like(arr, 7.1) //请注意,full_like函数在填充时会根据arr内类型进行类型转换,比如arr的数据类型原来为int型,会将7.1变为7 //创建diagnal(一般是主对角线) np.eye(5) [[1. 0. 0. 0. 0.] [0. 1. 0. 0. 0.] [0. 0. 1. 0. 0.] [0. 0. 0. 1. 0.] [0. 0. 0. 0. 1.]] eye的k参数,正数代表向右平移,负数代表向左平移(是指主对角线漂移) // 通过已有数组创建元素类型不同的数组 arr = arr.astype(np.float)
-
//创建结构化数组示例 // 我可能想复杂了,其实往往不需要在后面写生dtype,除非有特殊需求 structured = np.array([(1, 'First', 0.5, 1+2j), (2, 'Second', 1.3, 2-2j), (3, 'Third', 0.8, 1+3j)], dtype=[('id', 'i2'), ('position', 'a6'), ('value', 'f4'), ('complexs', 'c8')]) //这样就可以通过像字典一样的形式来操作结构化数组 array([(1, b'First', 0.5, 1.+2.j), (2, b'Second', 1.3, 2.-2.j), (3, b'Third', 0.8, 1.+3.j)], dtype=[('id', '<i2'), ('position', 'S6'), ('value', '<f4'), ('complexs', '<c8')]) // 另一种方法来制定各字段名称 structured = np.array([(1, 'First', 0.5, 1+2j), (2, 'Second', 1.3, 2-2j), (3, 'Third', 0.8, 1+3j)], dtype=['i2', 'a6', 'f4', 'c8']) structured.dtype.names = ['id', 'position', 'value', 'complexs'] //改变dtype属性的names字段,这是给列取名字!!! //这样就可以像字典一样使用了, //结构化数组调用示例 structured['id']
数组的基本操作
运算的前提——广播与广播机制(umm……不太熟)
numpy可以实现元素级操作,同时numpy实现了对不同形状对象的运算,这种机制称为广播
广播机制:将两种不同形状的数组对象进行元素级运算的预处理机制(也就是升维),分为两个阶段。
[1]. 判断两个数组的各个维度是否兼容,如果兼容直接进行[2]。如果不兼容,再判断其中一个数组是否为一维,如果为一维也进行[2],否则不能进行.
[2]. 用已有的元素生成其他的元素
算数基本操作
算数运算符
+, -, *, /, %, **, //等所有算数运算符都是元素级运算符,结果返回新数组
注意:python中的*指的是元素级乘法,采用dot方法计算矩阵积
特殊的运算符:+=,-=(自增、自减最常用)等某等运算符可以直接更改对象
通用函数与运算(Universal function)
通用函数是指元素级操作函数,可以抽象为f(arr)
其中较常用的为dot(矩阵积),等。让人感动的是numpy重复实现了math库中绝大多数函数,以静态方法方式调用。
arr.T //数组转置
arr.flatten() //将数组将为1维,返回新的副本(意味着直接返回全新的数组对象,可以直接修改,注意这是与reshape不同的地方)
np.flat() //将数组将为1维,返回一个1维迭代器,可以用for循环遍历
arr.ravel() //将数组将为1维,返回视图(内存的位置是不变的!!!)
arr.astype(np.float) // 返回一个新数组,将原数组的数据经过float()处理
arr.swapaxes(ax1, ax2) // 将两个维度互换(换轴)
arr.transpose() // 不带参数时,效果相当于转置
arr.transpose(2, 1, 0) // 相当于将arr的三个轴转换到新位置
arr.tolist() //将ndarray转换为列表,如果使用哦那个list()函数转换,其实是相当于向量函数作用在ndarray上,是向量操作,打不傲tolist()的的效果
arr.tostring() // 将ndarray转换为字符串
// arr形状转换等其他实现参照创建数组章节
聚合函数(Group function)
聚合函数是指对一组值(往往是一个数组)进行操作,返回单一值。
其中常用的有:sum, min, max, mean, std(标准差)
索引与切片(花式索引、布尔索引)—— 需要更多的练习
索引的操作与标准库中的list相同,一起回忆一下:
操作相同但是返回值类型有区别:list的切片得到副本,而数组的切片得到视图
副本可以理解为原对象变化不对副本产生影响(当然有深浅copy之分,这里不赘述了),视图就像是SQL数据库中的视图,原对象变化会导致视图对象发生变化,倘若数组想要得到副本可以使用实例方法copy来得到
//一维数组索引示例 (在python中切片与索引(花式索引除外)返回的是副本,但在numpy中只返回视图!!!需要用copy与deep copy来创建副本)
a = np.arange(10)
a[2] = 2
a[-1] = 9 //反向索引也很常见,相当于从第一个元素反着查
//数组切片示例(结果很显然,不写了)
a[:]
a[1:2] //闭开区间
a[1:]
a[:8]
a[1:9:2] //带步长的切片
a[::-1] // 逆序地去除所有数据
//二维数组切片示例(多维数组以此类推)
A = np.array([range(10), range(10, 20)])
A[1, 2] // 选出第一行、第三列元素
A[1] //相当于选取第二行,当然还有更标准的写法,见下一个
A[1,:] //选取第2行,这相当于是省略了1轴的操作,这个逗号甚至可以省掉
A[:,1] //选取第2列 切记!零轴空操作,就是指前面的那个冒号,是不能被省略的!
// 注意!!!A[1]这种索引式返回结果是降维后的结果!!!而切片式返回的数组与原数组位数相同
// 分别在0轴和1轴上切分,输出为两个轴切出的交集
A[0:2, 0:2] //选取一个子矩阵
// 索引与切片相结合,因为有索引所以降了一个维度哦!
A[1, :2]
// 花式索引!!!
// 还是索引产生的副本!!!这与其他的取法不同!!!
A[[1, 9]:2] //列表(序列均可)可选取我们要拿出来的单列,是花式索引!!!(花式索引甚至可以重复放并且支持负数)
// 花式索引的另一种情况,将有高维数数组作为索引传入一维数组,会得到与高维数组相同形状的切片!!!
arr = np.arange(9)
b = np.arange(4).reshape(2, 2)
arr[b]
// 花式索引应用在二维数组(不熟)
arr = np.arange(15).reshape(4, 4)
// 布尔索引,也就是布尔数组作为索引,只取出值为True对应的值(不熟)
// 不同种索引相互配合
数组迭代
最初级的方法是使用foreach循环
更pythonic的方法是使用apply_along_axis()函数——直接对行、列整体进行操作
np.apply_along_axis(function, axis, arr)
//下面是对行求平均值的示例
np.apply_along_axis(np.mean, axis=1, arr=A)
//非常值得注意的地方!axis是along which axis的含义!尤其是之后的split都是这样!
//被我们操作的函数可以是自己定义的
数组筛选与bool数组
A = np.arange(-8, 8).reshape((4, 4))
//array([[-8, -7, -6, -5],
// [-4, -3, -2, -1],
// [ 0, 1, 2, 3],
// [ 4, 5, 6, 7]])
A[A > 0] //筛选出数组中符合要求的元素,以一位数组返回
A > 0 //相当于一个元素级操作,返回bool数组
数组的形状变换
包括前面提到过的reshape, shape。
ravel方法可以得到二维数组对应的一维数组(返回新数组)
transpose方法可以实现转置以及换轴(返回新数组)swapaxes也可以实现换轴
数组切分
数组的切分靠split族函数来实现:vsplit,hsplit,split
其实split完全可以代替vsplit与hsplit
//vertival split
[B, C] = np.vsplit(A, 2) //将A切为两部分,默认沿着列
[B, C] = np.hsplit(A, 2) //将A切为两部分,默认沿着行
//更为复杂但更灵活的split函数
[A1, A2, A3] = np.split(A, [1, 3], axis=1) //沿着1轴(就是沿着columns切)将A抽取[1, 3]后分成三部分
数组拷贝
在numpy中唯一为ndarray创建副本的方法是使用copy方法
浅拷贝就是指直接的赋值 a = b
这与python不同,python的copy函数是浅拷贝,deepcopy函数才是深拷贝
数组数据文件的读写
numpy提供 save, load函数来保存与读取二进制文件,getfromtxt从文本文件中读取
data = np.random.random((3, 3))
np.save('sava_data', data) //将data存在save_data.npy文件中,npy是默认保存拓展名
dataget = np.load('save_data.npy') //读取数据
//读取文本文件数据示例
data = getfromtxt('data.csv', delimiter=',', names=True) //delimiter是分隔符,由于为CSV文件,分隔符自然为逗号
//names代表数据中是否含有标题
//缺失的数据会被补成nan
事实上这些读取的工作常常由pandas来操作
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端