python数据分析---Numpy

发布时间:2026/9/6 8:24:27
python数据分析---Numpy Numpy什么是NumPyPython普通列表list是为通用数据设计循环很慢。NumPy专门做数字计算底层是C语言运算速度快几十上百倍是数据分析、机器学习的基础库。1. NumPy 内置了并行运算功能当系统有多个核心时做某种计算时NumPy 会自动做并行计算。2. NumPy 底层使用 C 语言编写内部解释器全局解释器锁其对数组的操作速度不受 Python 解释器的限制效率远高于纯 Python 代码。3. 有一个强大的 N 维数组对象 Array一种类似于列表的东西。安装pip install numpy固定导入写法import numpy as np安装 Jupyter 学习 NumPy 相对方便通过 pip install jupyter 安装pip install numpy pip install jupyterNumpy数组和Python列表性能对比import time import numpy as np start_time time.time() a [] for x in range(100000): a.append(x**2) end_time time.time() print(%.6f%float(end_time-start_time))# 0.011967897415161133 start_time time.time() a np.arange(100000)**2 end_time time.time() print(%.6f%float(end_time-start_time))1. ndarray 数组ndarray是NumPy的核心多维数组对象全称 n-dimensional arrayn 维数组。普通 Python 列表可以放不同类型数据[1,abc,3.5]NumPy 数组 ndarray全部元素必须是同一个类型全是整数 / 全是小数创建数组np.array 对象np.array()是 NumPy 最核心函数作用把 Python 列表 / 元组等序列转换成 NumPy 数组对象ndarray 对象返回的对象类型叫 ndarray基础语法np.array(object, dtypeNone, copyTrue, orderNone, ndmin0)import numpy as np 把python列表转numpy数组 arr np.array([[1,2,3], [4,5,6]]) print(arr) #[[1 2 3] [4 5 6]] print(维度ndim, arr.ndim) # 2 print(形状shape, arr.shape) # (2,3) 2行3列 print(元素总数size, arr.size) # 6 2*36 print(数据类型dtype,arr.dtype) # int64 整数 print(单个元素占字节itemsize,arr.itemsize)解析object必传参数输入数据可以是列表、元组或嵌套列表。ndim维度。一维就是向量二维就是表格矩阵。shape格式为行数列数通过它就能看出数组的结构。size数组中元素的总个数。dtype数组中元素的数据类型如 int 整数、float 小数。itemsize单个元素占用字节数。指定数据类型# 强制设置为32位浮点数 a np.array([1,2,3], dtypenp.float32) print(a.dtype) 转换类型astype会生成新数组不会改原来的 b a.astype(np.int32) print(b.dtype)⚠️小白坑astype()不会修改原数组要接收返回值。2. 创建数组① 创建全0、全1数组# 参数传元组(行数,列数) zero_arr np.zeros((2,3)) print(zero_arr) [[0. 0. 0.] [0. 0. 0.]] one_arr np.ones((3,2)) print(one_arr) 全部填充同一个数字 full_arr np.full((2,2), 8) print(full_arr) [[8 8] [8 8]] 解析np.zeros((行,列))括号里面要传元组不能写np.zeros(2,3)会报错② 生成数字序列# np.arange(起点,终点,步长)左闭右开取不到终点数字 a1 np.arange(0,10,2) print(a1) # [0 2 4 6 8] linspace起点到终点一共生成多少个点包含首尾 a2 np.linspace(0, 10, 5) print(a2) # [ 0. 2.5 5. 7.5 10. ]对比记忆arange按步长取数字不一定包含终点linspace指定一共多少个数字首尾一定包含linspace linear space线性等间距采样作用在[start, stop]区间生成指定个数的均匀间隔的一维 ndarray 数组。重点你告诉它要多少个点numpy 自动计算两点之间步长。np.linspace(start, stop, num50, endpointTrue, retstepFalse, dtypeNone)参数说明start序列起点包含stop序列终点默认包含左闭右闭[start, stop]num生成多少个样本点默认50必须≥0endpointTrueTrue把 stop 作为最后一个元素False不包含终点retstepFalseTrue 时返回元组(数组,步长step)同时返回算出的间隔大小dtype指定输出数组的数据类型③ 随机数数组# 设置随机种子写一样的种子每次运行随机数都一样方便调试 np.random.seed(10) rand(行,列) 生成0~1之间的小数 r1 np.random.rand(2,3) print(r1) randint(最小值,最大值,(行,列))整数取不到最大值 r2 np.random.randint(0,10,(3,3)) print(r2)1️⃣np.random.seed(种子数字)随机种子核心作用固定随即结果只要种子数字相同每次运行代码生成的随机数组完全一模一样方便调试、复现实验。只对后面的随机函数生效写一次即可不需要每次生成随机数都写。如果不写 seed每次运行得到的随机数都会不一样。示例np.random.seed(10) print(np.random.rand(2)) # 不管运行多少次输出永远是 [0.77132064 0.02075195]2️⃣np.random.rand(行,列)生成[0,1)区间的浮点数包含 0不包含 1参数直接写维度rand(2,3)→2 行 3 列数组注意rand()参数是分开写不是传元组rand(2,3)✔rand((2,3))也可以但习惯分开写。3️⃣np.random.randint(low, high, size)随机整数语法np.random.randint(最小值, 最大值, (行数,列数))取值范围[low , high)能取到最小值取不到最大值例子randint(0,10,(3,3))→ 整数范围0,1,2,...,9永远不会出现 10第三个参数size传入元组指定数组形状。3. 数组形状操作reshape视图view不复制新内存和原数组共用一份数据改视图原数组也变reshape只改变数组的形状不改变元素数量、不改变内存里真实的数据。总元素数量必须严格匹配否则报错原始arr np.arange(6)一共 6 个元素。reshape(2,3)→ 2×36 ✔合法reshape(3,2)→3×26 ✔合法reshape(2,2)→2×24≠6 ❌直接报错-1自动推导维度-1代表这个维度交给 numpy 帮我自动算出来reshape 里面最多只能写一个 - 1。想要独立副本不影响原数组调用.copy()强制复制一份新内存arr2 arr.reshape(2,3).copy() # 此时arr2是拷贝修改arr2不会改动arrarr np.arange(6) print(arr) # [0 1 2 3 4 5] reshape修改形状总数元素必须匹配6个元素只能改成23不能改成22 arr2 arr.reshape(2,3) print(arr2) [[0 1 2] [3 4 5]] -1交给numpy自动计算维度 arr3 arr.reshape(-1,2) print(arr3) 一共6个元素每一行2个自动算出有3行 → (3,2)ravel() vs flatten()多维→一维arr np.array([[1,2],[3,4]]) a arr.ravel() ravel展平优先返回【视图】共用内存 b arr.flatten() flatten展平永远返回【拷贝】全新内存互不干扰ravel能不拷贝就不拷贝flatten一定拷贝一份新的。reshape() vs resize()核心区别reshape不改变原数组返回新视图元素总数必须完全匹配resize直接修改原数组可以改变元素总个数import numpy as np # reshape返回新数组元素总数必须匹配支持-1自动算维度 a np.arange(12) b a.reshape(3, 4) print(reshape结果\n, b) print(reshape原数组不变, a) c a.reshape(-1, 6) print(reshape(-1,6)\n, c) # resize原地修改原数组可改总元素多出补0 arr np.arange(12) arr.resize(4, 3) print(\nresize(4,3)\n, arr) arr.resize(5, 5) print(resize扩大补0\n, arr)对比表方法reshape()resize()是否修改原数组❌不修改返回新数组✅直接修改原数组元素总数总数必须相等否则报错可以变大/变小多出补0不够直接截断自动维度支持‑1自动推算不支持‑1易错reshape一定要接收返回值原数组不变a.reshape(3,4) #错误结果丢弃a没变 a2 a.reshape(3,4) #正确resize直接改自己不需要赋值接收arr.resize(4,3) #直接生效不用 arr arr.resize(4,3)复制区分视图和真拷贝ori np.array([1,2,3]) view ori[:] #切片得到视图共享内存 copy ori.copy()#真正复制两块独立内存 view[0] 99 print(ori) # [99 2 3] 原数组被修改 copy[0] 100 print(ori) # [99 2 3] copy修改不会影响原数组易错切片得到视图修改切片会把原始数组改掉不想改原数组就用.copy()转置和 reshape 一样不复制新内存共用底层数据修改转置后的数组原数组也会变import numpy as np arr np.array([[1,2,3], [4,5,6]]) print(arr.shape) # (2, 3) 2行3列 写法1.T 最简洁二维最常用 arr_T arr.T print(arr_T) [[1 4] [2 5] [3 6]] #行变列列变行 print(arr_T.shape) # (3, 2) 3行2列 #写法2.transpose() arr_T2 arr.transpose() #想要独立副本 tarr.T.copy()拼接、分割数组a np.array([[1,2],[3,4]]) b np.array([[5,6],[7,8]]) axis0上下拼接行变多纵向 c1 np.concatenate([a,b],axis0) print(c1) axis1左右拼接列变多横向 c2 np.concatenate([a,b],axis1) print(c2) c1 concatenate([a,b],axis0) [[1 2] [3 4] [5 6] [7 8]] shape (4,2)行数变多 c2 concatenate([a,b],axis1) [[1 2 5 6] [3 4 7 8]] shape (2,4)列数变多axis简单理解axis0→ 沿着行方向操作上下axis1→ 沿着列方向操作左右axis0上下拼接列数必须相同行数可以不一样axis1左右拼接行数必须相同列数可以不一样a np.array([[1,2],[3,4]]) # shape(2,2) b np.array([[5,6]]) # shape(1,2) np.concatenate([a,b],axis0) # ✔列都是2可以上下拼 np.concatenate([a,b],axis1) ❌行数不一致报错vstack等价axis0hstack等价axis1np.vstack([a,b])⇔np.concatenate([a,b], axis0)上下堆np.hstack([a,b])⇔np.concatenate([a,b], axis1)左右拼np.split(数组, 分割点列表, axis?)axis0按行切割横向切开切成好几块axis1按列切割纵向切开arr np.arange(12).reshape(4,3) # 在行索引 2 的位置切开切成两块 parts np.split(arr,[2],axis0) print(parts[0]) #前2行 print(parts[1]) #后2行np.vsplit等价axis0np.hsplit等价axis1。concatenate 第一个参数是数组列表[a,b]不要写成a,b。axis0 上下要求列数相等axis1 左右要求行数相等。vstack/hstack 只是 concatenate 的简写。拼接出来是新拷贝数组不是视图修改拼接结果不会影响原数组。4. 索引切片取数组里的数据一维数组a np.array([10,20,30,40,50]) print(a[0]) #取第0个元素 10 print(a[1:3]) #切片下标1到2左闭右开 [20 30] print(a[::2]) #步长2隔一个取一个 [10 30 50]二维数组表格arr np.array([[1,2,3], [4,5,6], [7,8,9]]) arr[行下标 , 列下标] 逗号分隔 print(arr[0,1]) #第0行第1列 → 2 print(arr[1:3, 0:2]) 行取1,2两行列取0,1两列 print(arr[2,:]) #第2行所有列 print(arr[:,1]) #所有行第1列 import numpy as np a1 np.arange(0,29) 1. 获取某⾏的数据 数组名[索引] a1[1] a1 np.arange(0,24).reshape((4,6) [[ 0 1 2 3 4 5] [ 6 7 8 9 10 11] [12 13 14 15 16 17] [18 19 20 21 22 23]] a[2] #获取下标为2的整行第3行 a[2,:]#标准写法 #- 逗号前面行下标 #- 逗号后面:代表所有列 a[2][:] # Python列表风格numpy不推荐性能差 2. 连续获取某几行数据 a[1:3, :]# 获取下标1、2两行第2、3行 1:3行从1取到3 之前取 1、2 : 代表所有列不能省略 a[0:2, :] # 取第0、1行前2行 a[1:, :] # 从下标1一直到最后所有行 a[:3, :] # 从开头到下标3之前取0,1,2行 a[-2:, :] # 取最后2行 a[:, 1:4] # 所有行第1,2,3列 #注意a[1:3]也可以运行省略后面的,:但考试写完整 a[1:3, :]更规范 3. 获取某⾏某列的数据 a[0,0] #第0行第0列左上角第一个元素 →0 a[1,2] #第1行第2列 →8 a[-1,-1] #最后一行最后一列 →23 4. 获取某列的数据 a[:, 0] # 第0列第一列 a[:, -1] # 最后一列 #连续取多列 a[:, 1:4] # 所有行列下标1、2、3左闭右开小白注意推荐逗号写法arr[i,j]不要写arr[i][j]总结如果数组是一维的那么索引和切片就和 Python 中的列表是一样的。如果是多维的那么在中括号中给两个值两个值是通过逗号分隔的逗号前面是行后面是列。如果中括号中只有一个值那么就表示行。如果是多维数组那么行的部分和列的部分都是遵循一维数组的方式可以使用整形、切片还可以使用中括号的形式来代表不连续的。布尔索引条件筛选arr np.array([1,2,3,4,5]) mask arr 2 print(mask) # [False False True True True] 用布尔数组当掩码取出条件成立的元素 res arr[mask] print(res) # [3 4 5]多条件必须用 | ~每个条件加括号不能用and orres arr[(arr1) (arr4)] print(res)并且|或者~非取反花式索引整数数组索引arr np.arange(10) res arr[[0,2,4]] print(res) #取下标0、2、4的元素 [0 2 4]⚠️重点普通切片是视图布尔索引、花式索引返回拷贝修改结果不会影响原数组。值的替换import numpy as np # 1.切片/索引替换 arr np.arange(12).reshape(3, 4) print(1.切片索引替换) print(原始数组\n, arr) arr[1, :] 99 # 修改第1整行 print(修改第1行后\n, arr) arr[:, 2] 88 # 修改第2整列 print(修改第2列后\n, arr) arr[0:2, 0:2] 0 # 修改局部一块区域 print(局部切片替换后\n, arr) # 2.条件布尔索引替换原地修改原数组 arr np.arange(12).reshape(3, 4) print(\n2.条件布尔替换) print(原始数组\n, arr) arr[arr 5] -1 # 大于5替换为-1 print(大于5替换成-1\n, arr) # 3.np.where()替换返回新数组原数组不变 arr np.arange(12).reshape(3, 4) print(\n3.np.where替换) print(原始数组\n, arr) new_arr np.where(arr 5, 1, 0) print(where处理后的新数组\n, new_arr) print(原数组不变\n, arr) # 考试高频示例奇数替换-1 print(\n高频例题奇数替换为‑1) arr1 np.arange(10) arr1[arr1 % 2 1] -1 print(布尔原地替换结果, arr1) arr2 np.arange(10) res_where np.where(arr2 % 2 1, -1, arr2) print(where新数组结果, res_where) print(where原数组, arr2)whereimport numpy as np #模式1三参数where(条件,x,y)返回新数组原数组不变 arr np.array([1, 6, 3, 8, 2]) res np.where(arr 4, 99, 0) print(模式1原数组, arr) print(where结果, res) arr2 np.arange(10) res2 np.where(arr2 % 2 1, -1, arr2) print(奇数替换-1, res2) print(原数组不变, arr2) #模式2仅传条件获取满足条件的下标 arr3 np.array([1, 6, 3, 8, 2]) idx np.where(arr3 4) print(\n满足条件下标, idx) print(取出元素, arr3[idx]) #二维where a2d np.arange(12).reshape(3, 4) pos np.where(a2d 8) print(二维行索引, pos[0]) print(二维列索引, pos[1]) #对比布尔索引原地修改 arr_test np.array([1, 6, 3, 8, 2]) arr_test[arr_test 4] 99 print(\n布尔索引原地修改, arr_test)numpy索引和切片的练习1.将np,arange(10)数组中的奇数全部都替换成-1.2.有⼀个4⾏4列的数组⽐如np.random.randint(0,10,size(4,4)),请将其中对⻆线的数取出来形成⼀个⼀维数组提示(使⽤np.eye)·3.有⼀个4⾏4列的数组请取出其中(0,0),(1,2),(3,2)的点。124.有⼀个4⾏4列的数组请取出其中2:3⾏(包括第3⾏)的所有数据。5.有⼀个8⾏9列的数组请将其中1-6⾏(包含第5⾏)的第8列⼤于3的数全部都取出来。6.替换数组中所有⼩于平均值的元素7.将⼀个数组的边框元素设置为08.反转⼆维数组的⾏9. 将3D数组的最后⼀个维度进⾏求和10.选择数组中的⾮对⻆线元素import numpy as np 1. 将np.arange(10)数组中的奇数全部都替换成-1 arr np.arange(10) arr[arr % 2 1] -1 print(1.奇数替换-1\n, arr) 2. 4×4数组取出对角线元素形成一维数组 np.random.seed(0) a2 np.random.randint(0, 10, size(4, 4)) diag a2[np.eye(4, dtypebool)] print(\n2.对角线元素\n, diag) 3. 4×4数组取出(0,0),(1,2),(3,2)的点 np.random.seed(1) a3 np.random.randint(0, 10, (4, 4)) res3 a3[[0, 1, 3], [0, 2, 2]] print(\n3.指定坐标取值\n, res3) 4. 4×4数组取出2:3行(包括第3行)所有数据 a4 np.random.randint(0, 10, (4, 4)) res4 a4[1:3, :] print(\n4.第2、3行\n, res4) 5. 8行9列数组取出1‑6行(包含第5行)的第8列大于3的全部数 a5 np.random.randint(0, 10, (8, 9)) sub5 a5[0:5, 7] res5 sub5[sub5 3] print(\n5.筛选结果\n, res5) 6. 替换数组中所有小于平均值的元素 a6 np.random.randint(0, 10, (5, 5)) mean_val a6.mean() a6[a6 mean_val] 0 print(\n6.小于均值置0\n, a6) 7. 将数组的边框元素设置为0 a7 np.ones((5, 5)) a7[0, :] 0 a7[-1, :] 0 a7[:, 0] 0 a7[:, -1] 0 print(\n7.边框置0\n, a7) 8. 反转二维数组的行 a8 np.arange(12).reshape(4, 3) res8 a8[::-1, :] print(\n8.反转行\n, res8) 9. 将3D数组的最后一个维度进行求和 a9 np.arange(24).reshape(2, 3, 4) res9 a9.sum(axis2) print(\n9.3D最后一维求和 shape, res9.shape) print(res9) 10. 选择数组中的非对角线元素 a10 np.random.randint(0, 10, (4, 4)) mask ~np.eye(4, dtypebool) res10 a10[mask] print(\n10.非对角线元素\n, res10)5. 向量化运算 广播普通python列表做加法需要循环numpy数组可以直接加减乘除不用写for循环底层C跑速度飞快a np.array([1,2,3]) b np.array([4,5,6]) print(a b) # [5 7 9] print(a * b) # [ 4 10 18] print(a **2) # [1 4 9] print(a2) # [False False True]广播机制形状不一样的数组也能计算广播规则从最后一维开始对齐维度相等或者其中一个维度是1就可以自动复制扩展进行运算。例子1数组和单个数字运算a np.array([1,2,3]) res a 10 print(res) # [11 12 13] # 数字10相当于 [10,10,10]自动广播例子2二维一维# (3,1) 3行1列 x np.ones((3,1))#np.ones()生成全部元素为1的数组 # (1,4) 1行4列 y np.ones((1,4)) z x y print(z.shape) # (3,4)np.newaxis用来增加维度x np.array([1,2,3]) print(x.shape) # (3,) x2 x[:, np.newaxis] print(x2.shape) # (3,1)6. ufunc通用函数对数组每一个元素计算数学函数arr np.array([1,4,9]) print(np.sqrt(arr)) #开根号 [1. 2. 3.] print(np.exp(arr)) #e的次方 print(np.abs([-1,-2])) #绝对值统计函数 sum mean max minaxis0沿着列运算把每一列算成一个值axis1沿着行运算把每一行算成一个值arr np.array([[1,2], [3,4]]) print(arr.sum()) #全部求和 10 print(arr.sum(axis0)) #按列求和 [4 6] print(arr.sum(axis1)) #按行求和 [3 7] print(arr.max()) #最大值 print(arr.argmax()) #最大值所在下标 print(arr.mean()) #平均值 print(arr.std()) #标准差np.where 条件选择arr np.array([1,-2,3,-4]) # np.where(条件条件满足取这个不满足取这个) res np.where(arr0, arr, 0) print(res) # [1 0 3 0]7. 矩阵运算 linalg模块⚠️超级大坑*代表对应位置数字相乘不是矩阵乘法✅矩阵乘法用或者np.dot()A np.array([[1,2],[3,4]]) B np.array([[1,0],[0,1]]) element_mul A * B #逐元素相乘 mat_mul A B #数学矩阵乘法 print(element_mul) print(mat_mul) #求逆矩阵 inv_A np.linalg.inv(A) #行列式 det_A np.linalg.det(A)8. 文件读写arr np.arange(10) #保存numpy专用二进制文件速度快 np.save(test.npy, arr) data np.load(test.npy) #读写csv文本 np.savetxt(out.csv,arr,delimiter,) read_data np.loadtxt(out.csv,delimiter,)