NumPy

NumPy(Numerical Python)是Python的⼀种开源的数值计算扩展。提供多维数组对象,各种派⽣对象(如掩码数组和矩阵),这种⼯具可⽤来存储和处理⼤型矩阵,⽐Python⾃身的嵌套列表(nested list structure)结构要⾼效的多(该结构也可以⽤来表示矩阵(matrix)),⽀持⼤量的维度数组与矩阵运算,此外也针对数组运算提供⼤量的数学函数库,包括数学、逻辑、形状操作、排序、选择、输⼊输出、离散傅⽴叶变换、基本线性代数,基本统计运算和随机模拟等等。

  • ⼏乎所有从事Python⼯作的数据分析师都利⽤NumPy的强⼤功能
  • 强⼤的N维数组
  • 成熟的⼴播功能
  • ⽤于整合C/C++和Fortran代码的⼯具包
  • NumPy提供了全⾯的数学功能、随机数⽣成器和线性代数功能
  • 只有一个数据类型ndarray,但是同时只能存放一种基本数据类型,下标从0开始
  • numpy官方文档
  • numpy中文手册

安装使用

pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple
#pip3 install numpy

#import numpy

创建数组函数

  • numpy.empty(shape, dtype=float) : 方法用来创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组
  • numpy.zeros(shape, dtype=float) : 创建指定大小的数组,数组元素以0来填充
  • numpy.ones(shape, dtype=float) : 创建指定形状的数组,数组元素以1来填充

参数描述

  • shape : 指定行列数,可以指定多维通过list,tuple的形式均可
  • dtype : 数据类型
import numpy as np
# tab 代码提示,再按Tab 就是函数调用
# 在函数的 括号里 shift + tab 可以获得参数提示
#2行3列为0的浮点型数组
print(np.empty([2,3],dtype=float))
#3行3列的空字符串数组
print(np.zeros((3,3),dtype=str))
#3行3列为0的整型数组
print(np.zeros((3,3),dtype=int))
#3行3列为1的整型数组
print(np.ones((3,3),dtype=int))
#3行3列为1的整型数组 类型可以以字符串形式传递
print(np.ones((3,3),dtype='int64'))

结果输出

[[6.89798700e-307 2.00267682e-307 2.78150360e-307]
[4.00541815e-307 2.78148492e-307 1.76128176e-312]]

[['' '' '']
['' '' '']
['' '' '']]

[[0 0 0]
[0 0 0]
[0 0 0]]

[[1 1 1]
[1 1 1]
[1 1 1]]

[[1 1 1]
[1 1 1]
[1 1 1]]

用已有数据创建数组

  • numpy.asarray(object, dtype = None) : 将结构数据转换成ndarray数组,当数据源是ndarray时,为浅拷贝(原数据变化后,新数组也变化)
  • numpy.array(object, dtype = None) : 将结构数据转换成ndarray数组,当数据源是ndarray时,为深拷贝(原数据变化后,新数组不变化)
#利用列表进行创建数组
l1 = [1,2,3,4]
print(np.asarray(l1,dtype=str))
l2=[(1,2,3),(4,5,6),(7,8,9)]
print(np.asarray(l2))
l3=[5, 6, 7, 8]
print(np.array(l3,dtype=float))

#利用元组创建数组
t1 =(1,2,3,4)
print(np.array(t1))
t2 =((1,2,3),(3,4,5))
print(np.array(t2))

# 验证np.array 与 np.asarray 的区别,np.asarray为浅拷贝
arr1 = np.ones((3,3),dtype=int)
asarr = np.asarray(arr1) 
ar_arr1 = np.array(arr1)
arr1[1] =2
print(arr1)
print(asarr)
print(ar_arr1)

结果输出

#利用列表进行创建数组
['1' '2' '3' '4']

[[1 2 3]
[4 5 6]
[7 8 9]]

[5. 6. 7. 8.]

#利用元组创建数组

[1 2 3 4]

[[1 2 3]
[3 4 5]]

# 验证np.array 与 np.asarray 的区别,np.asarray为浅拷贝

[[1 1 1]
[2 2 2]
[1 1 1]]

[[1 1 1]
[2 2 2]
[1 1 1]]

[[1 1 1]
[1 1 1]
[1 1 1]]

从数值范围创建数组

  • numpy.arange(start, stop, step, dtype)

参数描述

  • start : 起始值,默认为0
  • stop : 终止值(不包含)
  • step : 步长,默认为1
  • dtype : 返回ndarray的数据类型,如果没有提供,则会使用输入数据的类型
#创建10到100 并且步长为10的数组(同切片一样包含开始,不包含结束)
arr1 = np.arange(10,100,10)
print(arr1)

# 结果
[10 20 30 40 50 60 70 80 90]
  • np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)

参数描述

  • start : 序列的起始值
  • stop : 序列的终止值,如果endpoint为true,该值包含于数列中
  • num : 要生成的等步长的样本数量,默认为50
  • endpoint : 该值为true时,数列中包含stop值,反之不包含,默认是True
  • retstep : 如果为True时,生成的数组中会显示间距,反之不显示。
  • dtype : ndarray的数据类型
#指定区间均匀分割创建数组
arr2 = np.linspace(10,100,10,endpoint=True,dtype=int)
print(arr2)

# 结果
[ 10  20  30  40  50  60  70  80  90 100]

利用随机函数创建数组

  • numpy.random.rand(dn) : 0-1之间均匀分布的浮点数
  • numpy.random.randn(dn) : 标准正态分布(均值为0,标准差为1)
  • numpy.random.randint(low,high,size) : 依据形状用low~high区间的数值创建数组
  • numpy.random.uniform(low,high, size) : 产生均匀分布的数组,起始值为low,high为结束值,size为形状
  • numpy.random.normal(loc, scale, size) : 产生正态分布的数组,loc为均值,scale为标准差,size为形状
#创建2行3列的0-1之间均匀分布浮点数
arr1 = np.random.rand(2,3)
print("0-1间均匀分布\n",arr1)
#创建3行3列的标准正态分布的浮点数
arr2 = np.random.randn(3,3)
print("正态分布\n",arr2)
#创建3,3列10-100之间的整数
arr3 = np.random.randint(10,100,(3,3))
print("10-100整数\n",arr3)
#创建3,3列10-100之间的浮点数
arr4 = np.random.uniform(10,100,(3,3))
print("10-100浮点数\n",arr4)
#创建3,3列正定均值,标准差的正态分布
arr5 = np.random.normal(80,10,(3,3))
print("均值为80,标准差为10的浮点数\n",arr5)

输出结果

#0-1间均匀分布

[[0.29497593 0.83171348 0.43229655]
[0.28426801 0.90516017 0.38341161]]

#正态分布

[[-1.04862542 -1.29375091  0.92648632]
[-1.55675552  0.8527372  -0.48236677]
[-0.48029127  2.03284023 -0.93163757]]

#10-100整数

[[39 47 93]
[68 33 75]
[96 20 46]]

#10-100浮点数

[[89.10309942 88.02850559 22.2223232 ]
[83.32027834 56.53886041 24.20109113]
[35.01408475 42.69099473 95.07580552]]

#均值为80,标准差为10的浮点数

[[80.09020601 89.21345912 68.49795065]
[67.0012265  75.19606176 73.8063407 ]
[87.48909856 71.63283437 83.96595267]]

数组属性

  • arr.dtype : 元素类型
  • arr.ndim : 数组维度
  • arr.shape : 数组形状
  • arr.size : 元素个数
arr1 = np.array([[1,2,3],[4,5,6]])
print("dtype",arr1.dtype) # int32
print("ndim",arr1.ndim) # 2
print("shape",arr1.shape) # (2, 3)
print("size",arr1.size) # 6

修改数组维度

  • arr.reshape(shape, order='C') : 返回改变维度后的数组
  • arr.resize(shape) : 改变当前数组维度
  • numpy.ravel(array,order="C") : 返回改变维度后的一维数组

参数描述

  • shape : 指定行列数,可以指定多维通过list,tuple的形式均可
  • order : C按行,F按列,A原顺序

区别

  • resize 无返回值(返回值为None),会改变原数组。
  • reshape 有返回值,返回值是被reshape后的数组,不会改变原数组。
  • resize 可以放大或者缩小原数组的形状:放大时,会用0补全剩余元素;缩小时,直接丢弃多余元素。
  • reshape 要求reshape前后元素个数相同,否则会报错,无法运行。
#5行4列的数组转换为10行2列的数组(要想改变元数组要重新赋值)
arr = np.random.normal(80,5,(5,4))
print(arr.reshape([10,2]))
arr.resize([4,5])
print(arr)

输出结果

[[74.50410143 79.85385333]
[69.01923402 75.68557736]
[73.10327129 75.23198585]
[79.08259875 77.0005062 ]
[86.10986076 87.40839827]
[80.69638411 83.56963886]
[81.7102163  87.87354462]
[81.34607894 82.97543228]
[75.38878448 75.71512295]
[75.78989293 77.78025783]]

[[74.50410143 79.85385333 69.01923402 75.68557736 73.10327129]
[75.23198585 79.08259875 77.0005062  86.10986076 87.40839827]
[80.69638411 83.56963886 81.7102163  87.87354462 81.34607894]
[82.97543228 75.38878448 75.71512295 75.78989293 77.78025783]]

数组访问与修改

ndarray对象的内容可以通过索引或切片来访问和修改,与 Python 中 list 的切片操作一样[开始:结束:步长].ndarray 数组可以基于0-n的下标进行索引

  • 一维数组
arr = np.arange(1,11)
print("arr\n",arr)
print("arr[::2]\n",arr[::2])
print("arr[1::2]\n",arr[1::2])
print("arr[:5]\n",arr[:5])
print("arr[5:]\n",arr[5:])

输出结果

arr
[ 1  2  3  4  5  6  7  8  9 10]
arr[::2]
[1 3 5 7 9]
arr[1::2]
[ 2  4  6  8 10]
arr[:5]
[1 2 3 4 5]
arr[5:]
[ 6  7  8  9 10]
  • 二维数组
#二维数组
arr=np.random.randint(1,100,(3,4))
print("arr\n",arr)
#通过行索引访问行
print("arr[0]\n",arr[0])
#对行索引进行切片
print("arr[:2]\n",arr[:2])
#对行和列进行切片
print("arr[:2,2:]\n",arr[:2,2:])

输出结果

arr
[[95 23 83 92]
[93 60 22 64]
[70  4  8 31]]
arr[0]
[95 23 83 92]
arr[:2]
[[95 23 83 92]
[93 60 22 64]]
arr[:2,2:]
[[83 92]
[22 64]]

数组切片访问与修改

  • slice(stop) : 切片函数,等价于:结束
  • slice(start,stop ,step) : 等价于开始:结束:步长

参数描述

  • start : 开始标记,包含
  • stop : 结束标记,不包含
  • step : 步长
ar = np.arange(1,13).reshape([3,4])
print(ar)
print(ar[:2])
print(ar[slice(2)])
print(ar[:,::2])
print(ar[slice(3),slice(0,4,2)])
#取1,3行
print(ar[np.arange(0,3,2)])

输出结果

[[ 1  2  3  4]
[ 5  6  7  8]
[ 9 10 11 12]]

[[1 2 3 4]
[5 6 7 8]]

[[1 2 3 4]
[5 6 7 8]]

[[ 1  3]
[ 5  7]
[ 9 11]]

[[ 1  3]
[ 5  7]
[ 9 11]]

[[ 1  2  3  4]
[ 9 10 11 12]]

利用True,False进行访问与修改

通过相等形状的元素为True,False的数组对数据进行获取,通过对数组进行判断的形式得到相同形状的True,False数组

#大于10的数
ar = np.arange(1,21).reshape((4,5))
print(ar)
# 5的倍数
print(ar[ar % 5==0])
# 奇数
print(ar[ar % 2==1])
# 偶数
print(ar[ar % 2==0])

输出结果

[[ 1  2  3  4  5]
[ 6  7  8  9 10]
[11 12 13 14 15]
[16 17 18 19 20]]

[ 5 10 15 20]

[ 1  3  5  7  9 11 13 15 17 19]

[ 2  4  6  8 10 12 14 16 18 20]

算数函数

  • numpy.add(arr1,arr2或常数) : 数组+常数,相同shape或相同行或相同列数组相加
  • numpy.substract(arr1,arr2或常数) : 数组-常数,相同shape或相同行或相同列 数组相减
  • numpy.multiply(arr1,arr2或常数) : 数组*常数,相同shape或相同行或相同列 数组相乘
  • numpy.divide(arr1,arr2或常数) : 数组/常数,相同shape或相同行或相同列数组相除
  • numpy.exp(arr) : e**arr
  • numpy.power(arr1,arr2或常数) : 等价于**
  • numpy.mod(arr1,arr2或常数) : 数组%常数,相同shape或相同行或相同列数组取余
  • numpy.modf(arr) : 分开整数部分和小数部分
  • numpy.log(arr) : ln,表示e的多少次方为此数组的元素值
  • numpy.log2(arr) : log以2为底的对数
  • numpy.log10(arr) : log以10位底的对数
  • numpy.sqrt(arr) : 对数组进行开方
  • numpy.square(arr) : 当前数组二次幂
  • numpy.around(arr,小数点位数) : 4舍5入后保留指定位数的小数点
  • numpy.floor(arr) : 向下取整
  • numpy.ceil(arr) : 向上取整
  • numpy.sign(arr) : 取符号,正数为1,0,负数为-1

字符串函数

  • numpy.char.add(arr_str,arr2或常数) : 不能用+号代替
  • numpy.char.multiply(arr_str,arr2或常数) : arr2或常数 是整数(重复字符串次数)
  • numpy.char.center(arr_str,长度,fillchar="不够长度填充字符") : 将字符串居中,并使用指定字符在左侧和右侧进行填充
  • numpy.char.capitalize(arr_str) : 首字母大写
  • numpy.char.strip(arr_str) : 去掉左右两侧空格
  • numpy.char.lstrip(arr_str) : 去掉左空格
  • numpy.char.rstrip(arr_str) : 去掉右空格
  • numpy.char.lower(arr_str) : 所有字母变小写
  • numpy.char.upper(arr_str) : 所有字母变大写
  • numpy.char.split(arr_str,sep=分隔符) : 按指定分隔符分割
  • numpy.char.replace(arr_str,old="要替换掉的字符","新字符") : 指定字符替换
list1 = [["lili","Jim","Tom","son"],[" bijing","shang hai","tian jin","shen zhen   "]]
ar = np.array(list1)
np.char.replace(ar[1],"I","i")
print(np.char.split(ar[1],sep=" "))
print(np.char.split(ar[0,1]))
ar = np.char.upper(ar)
print(ar)
print(np.char.lower(ar))
ar = np.char.lstrip(ar)
print(ar)
print(np.char.capitalize(ar))
print(np.char.center(ar[0],10,fillchar="*"))
print(np.char.multiply(ar[0],np.asarray([2,3,4,5])))
print(np.char.add(ar[0],"_name"))

结果输出

[list(['', 'bijing']) list(['shang', 'hai']) list(['tian', 'jin'])
list(['shen', 'zhen', '', '', ''])]
['Jim']
[['LILI' 'JIM' 'TOM' 'SON']
[' BIJING' 'SHANG HAI' 'TIAN JIN' 'SHEN ZHEN   ']]
[['lili' 'jim' 'tom' 'son']
[' bijing' 'shang hai' 'tian jin' 'shen zhen   ']]
[['LILI' 'JIM' 'TOM' 'SON']
['BIJING' 'SHANG HAI' 'TIAN JIN' 'SHEN ZHEN   ']]
[['Lili' 'Jim' 'Tom' 'Son']
['Bijing' 'Shang hai' 'Tian jin' 'Shen zhen   ']]
['***LILI***' '***JIM****' '***TOM****' '***SON****']
['LILILILI' 'JIMJIMJIM' 'TOMTOMTOMTOM' 'SONSONSONSONSON']
['LILI_name' 'JIM_name' 'TOM_name' 'SON_name']

统计函数

集中趋势

  • numpy.mean() : 统计数组元素的平均值
  • numpy.median(arr) : 统计数组元素的中位数
  • numpy.percentile(arr,q=[0-100 的数表示百分位点]) : 沿指定轴计算数据a的第q百分位
ar = np.random.randint(1,10,4)
print(np.mean(ar))
print(np.median(ar))
print(np.percentile(ar,q=[25,50,75]))

输出结果

5.5
5.0
[4.5 5.  6. ]

QQ截图20230518095120.jpg

离散程度

  • np.var(arr) : 方差
  • arr1.std() : 标准差
  • arr1.ptp() : 极差
ar = np.random.randint(1,10,4)
print(np.var(ar),np.std(ar),np.ptp(ar))
per =np.percentile(ar,[25,75])
# 四分位差
IQR = per[1] - per[0]
print(IQR)
#离散系数 σ/μ 标准差除以均值  作用:比较不同数据源的离散程度
v = np.std(ar) /np.mean(ar)
print(v)

输出结果

0.1875 0.4330127018922193 1
0.25
0.07530655685082074
  • numpy.diff() : 沿着指定轴计算第N维的离散差值
ar = np.random.randint(1,10,4)

ar2=np.diff(ar)
print(ar2)

np.diff(ar,n=2) # 一阶基础上进行2阶差分
np.diff(ar2,n=1)

输出结果

[-2, -3,  0]

[-1,  3]

QQ截图20230518095142.jpg

分布形态

  • arr.max() : 寻找最大值
  • arr.argmax() : 返回最大值的索引
  • arr.min() : 寻找最小值
  • arr.argmin() : 返回最小值的索引
  • arr.sum() : 指定维度的元素进行求和
ar = np.random.randint(10,100,(3,4))
print(np.max(ar),np.min(ar),np.argmax(ar),np.argmin(ar),np.sum(ar))

#第一行中最大的数所对应的,2,3行的数
ar[1:,ar[0] == np.max(ar[0])]

输出结果

93 19 6 9 702

array([[70],[19]])
  • numpy.sort(arr,axis) : 排序(更改原数组)
  • numpy.diff(arr,n,axis) : 差分
  • numpy.where(条件,True_value,False_Value) : 满足条件,返回True_value,否则返回 False_value
  • numpy.where(条件) : 返回符合条件的下标

参数描述

  • axis : 维0代表行,1代表列
  • n : 阶数
ar = np.random.randint(10,50,10)
ar = np.sort(ar)
print(ar[::-1])
print(np.diff(ar))
print(np.where(ar>40,1,0))
print(np.where(ar>20))

输出结果

[46 44 40 40 34 31 21 18 16 12]
[ 4  2  3 10  3  6  0  4  2]
[0 0 0 0 0 0 0 0 1 1]
(array([3, 4, 5, 6, 7, 8, 9], dtype=int64),)

文件IO操作

保存数组

  • np.save("文件名.npy",数组) : 保存ndarray到⼀个npy⽂件
  • np.savez("文件名.npz",key1 = 数组1,key2=数组2....) : 将多个array保存到⼀个.npz⽂件中
ar = np.random.randint(10,100,(3,4))
ar1 = np.random.randint(10,100,(3,4))
np.save("ar.npy",ar)
np.savez("d_ar.npz",one=ar,two=ar1)

读取数组

  • np.load(文件名.npy或.npz) : 读取存储的数组,如果是.npz⽂件的话,读取之后相当于形成了⼀个key-value类型的变量,np.load(文件名.npz).files 获得文件Key
f1 = np.load("ar.npy")
f2 = np.load("d_ar.npz")
print(f1,f2.files)

输出结果

[[80 95 46 18]
[76 44 84 45]
[33 82 92 55]] ['one', 'two']

读写csv、txt⽂件

  • numpy.savetxt("文件名.csv 或者 txt,数组,delimiter="元素分隔符") : 保存数组为csv、txt文件
  • numpy.loadtxt("文件名.csv 或者 txt,delimiter="元素分隔符") : 读取数组csv、txt文件
ar = np.random.randint(10,100,(3,4))
np.savetxt("test.csv",ar,delimiter=',')
np.loadtxt("test.csv",delimiter=",")

输出结果

array([[30., 30., 90., 59.],
        [18., 35., 78., 44.],
        [49., 36., 10., 63.]])