# 一,Numpy 知识点总结:
# 1, 创建 ndarray:
# 1)np.array()方法: 接收一切序列类型对象,包括其他数组。
import numpy as np
myndarry=np.array([1,2,3,4,"a","b"])
# 2)其他方法,如:np.zeros(),np.ones(),np.empty(),np.arange(),np.ones_like(),np.zeros_like(),
# np.eye(),np.empty_like(),np.identity()等。
np.zeros(5), np.zeros((2,3))
np.ones(5), np.ones((2,3))
np.empty((2,2)) # np.empty返回全0数组是不安全的,很多情况下,返回的都是一些未初始化的垃圾值.
np.arange(5), np.arange(1,5), np.arange(1,10,2) # array([0, 1, 2, 3, 4]) # 一维数组
arr02=np.zeros_like(arr01)
arr03=np.ones_like(arr01)
arr04=np.empty_like(arr01)
# 2, 数组的属性:
print(myarray.ndim) # 1 维数
print(myarray.size) # 5 元素总数
print(myarray.shape) # (5,) 形状 一维数组的形状 (n,)或(1,n)
print(myarray.dtype) # int32 数据类型
print(myarray.itemsize) # 4 每个元素的字节大小 32/8=4
# 3, ndarray 的数据类型:
# 1)自动推断类型:
arr01=np.array([0,1,2,3,4])
arr01.dtype # dtype('int32')
# 2)创建数组时为数组指定数据类型时:
arr02=np.array([0,1,2,3,4],dtype='float64')
arr02.dtype #dtype('folat64')
# 3)使用astype显示转换数据类型,返回一个新数组:
arr01=np.array([0,1,2.5,3.1,4.2],dtype='float64')
arr02=arr01.astype(np.int32) # 将浮点型数组转为整数,并不会四舍五入,而是直接截断 array([0, 1, 2, 3, 4])
arr01=np.array(['0','1','2.5','3.1','4.2'])
arr02=arr01.astype(np.float64)
arr02 # array([0. , 1. , 2.5, 3.1, 4.2])
arr01=np.array([0,1,2,3,4],dtype='float64')
arr02=np.array(["1","4","5"])
arr03=arr02.astype(arr01.dtype) # 使用其他数组的数据类型
arr03.dtype
# 4, 数组和标量之间的运算
# 大小相等的数组之间的任何算术运算都会将运算应用到元素级:
# 不同大小的数组之间的运算叫做广播,本书不对广播机制做深入了解,可在附录A NUmpy高级应用中了解一下。
arr*arr
arr+arr
arr-arr
arr/arr
arr**2
1/arr
arr-0.5
3*arr+2
arr>arr2 # 返回布尔类型数组
# 5, 基本索引和切片
# 1)一维数组: Numpy 数组的索引方法非常多,一维数组很简单和pyton 列表类似。
# 一维数组元素的访问:arr1d[5]
# 一维数组的切片:arr1d[5:8]
# 一维数组的切片赋值:arr1d[3:7]=12 会影响原数组的值
# 一维数组切片的显式复制: arr_new=arr1d[5:8].copy() 对 arr_new的修改,不会影响 arr1d
# 6, 高维数组的索引(访问)和切片: 二维数组 获取行,获取列,获取行列子集,获取元素
arr2d=np.arange(1,10).reshape(3,3)
# 二维数组的元素索引--获取一维数组(行):arr2d[2] 相当于 arr2d[2,] # array([7, 8, 9])
# 二维数组的元素索引--获取单个元素:arr2d[2][1] 相当于 arr2d[2,1] # 8
# 二维数组的元素索引--获取一维数组(列)arr2d[:,1] # 获取列需要切片 array([2, 5, 8])
# 二维数组的元素索引--获取二维的子集数组(行列子集)arr2d[:2,1:] # 获取行列子集需要切片
# 注意:
#上面所有的只要有两个[][]的都可以看作两次索引,比如 arr2d[2][1]相当于 arr_new01=arr2d[2] arr_new02=arr_new01[1]
#当然,对切片的赋值也会广播到整个选区:arr2d[:,:1]=9
# 7, 布尔索引 == != ~ | < > <= >=
# 返回结果的维度与布尔索引数组的维度相同:
names=np.array(["Bob","Joe","Will","Bob","Will","joe","joe"]) # size=7
data=np.random.randn(7,4) # 行数为 7
bool_Bob = names == 'Bob' # bool_Bob 是一个 size=7的一维布尔数组。 作为下面的索引条件,True表示满足条件
data[names == 'Bob'] 相当于 data[names == 'Bob',] # 返回所有满足条件的单行或多行 一维或二维数组
data[names == 'Bob',:4] 相当于 data[names == 'Bob',] # 前4列中满足条件的行 二维数组
data[names!='Bob']
data[~(names=='Bob')]
mask=(names=='Bob')|(names=='Will') data[mask] # 必须带括号
mask=(names=='Bob')&(names=='Will') data[mask] # 必须带括号 # data[mask]为空数组
# names中元素的值是确定的,不可能既是‘Bob’又是的'Will',所以可以预想 mask 的元素全是False
data[data<0]
# 对使用布尔索引获得的所有元素或行赋值:
data[data<0]=0 # 会影响 data
data[(data==0.1)|(data<0.2)]=0.25
data[names=='joe']=7
# 对使用布尔索引获得的整列赋值:
bool_arr=np.array([False,False,True,False])
data=data.swapaxes(0,1) # 轴对换返回的是一个新的数组,所以还用data来接收才能改变data数组。
data[bool_arr]=100 # 为列赋值
data=data.swapaxes(0,1) # 再次转回来
data
# 8, 花式索引(整数数组索引):
# 与切片的一个很大不同点是,它总是将数据复制到新数组中,对花式索引结果的赋值,不影响原数组,
# 因为其形状与原数组都不一样了,自然没法赋值给原数组。
arr84=np.empty((8,4))
for i in range(8):
# arr84[i,]=i
arr84[i]=i
arr84[[4,3,0,6]] # 取arr84数组的第5,第4,第1和第7行数据
arr84[[-3,-5,-7]] #使用负的索引,会从数组的末尾开始选行,-3表示倒数第三行。
newarr84=np.arange(32).reshape((8,4))
newarr84[[1,5,7,2],[0,3,1,2]]
newarr84[[1,5,7,2]][:,[0,3,1,2]] # 4x4 分开写:new=newarr84[[1,5,7,2]],new2=new[:,[0,3,1,2]] 输出new2
# 9,数组转置和轴对换
# 转置是重塑的一种特殊形式,返回的是原数组的视图(不会进行任何复制操作)
# 我的理解,arr和arr.T ,arr.transpose() 都是arr的不同形式,对arr.T ,arr.transpose()的赋值操作会影响arr
# 1)array.T 属性 2)arr.transpose(轴号元组)方法 3)array.swapaxes(1,0)方法
# 上面三种方法或属性都不改变原来数组。
arr35=np.arange(15).reshape((3,5))
arr35.T
arrdot=np.dot(arr35.T,arr35) # 点积操作
arr35=np.arange(15).reshape((3,5))
arr35.transpose((1,0)) # 轴号元组(1,0)
arr35.swapaxes(1,0) # 两个轴号做参数,不是元组
# 10,通用函数 ufunc:快速的元素级的数组函数
# 可以看作是简单函数(接受一个或多个标量值,并产生一个或多个标量值)的矢量化包装器。
# 许多ufunc都是简单的元素级变体,如sqrt,exp:
# 一元 ufunc:(操作单个数组) 语法:np.ufunc(arr)
# abs,fabs--计算整数,浮点数,复数的绝对值,对于非复数值,可以使用更快的fabs
# sqrt------计算各元素的平方根,相当于arr**0.5
# square----计算各元素的平方,相当于arr**2
# exp-------计算各元素的以e为底的指数
# log,log10,log2,log1p--分别表示自然对数,底数为10的log,底数为2的log,log(1+x)
# sign--计算各元素的正负号:1(正数),0(零),-1(负数)
# ceil--计算各元素的ceiling值,即大于等于该值的最小整数。 (天花板值)
# floor--计算该值的floor值,即小于等于该值的最大整数。(地板值)
# rint--将各元素的值四舍五入到最接近的整数,保留dtype。
# modf--将数组的小数和整数部分以两个独立数组的形式返回。
# isnan--返回一个表示哪些值是 NAN (not a number)的布尔型数组
# isfinite--返回一个表示哪些元素是有尽的(非inf,非NAN)的布尔型数组
# isinf--返回一个表示哪些元素是无穷的的布尔型数组
# cos,cosh,sin,sinh,tan,tanh--普通型和双曲型三角函数
# arccos,aeccosh,arcsin,arcsinh,arctan,arctanh--反三角函数
# logicl-not--计算各元素not x的真值。相当于 -arr
# 二元ufunc:(操作两个数组) 语法:np.ufunc(arr1,arr2)
# add--将两个数组中对应的元素相加
# subtract--将两个数组中对应的元素相减
# multiply--将两个数组中对应的元素相乘
# devide,floor_divide--除法或向下圆整除法(丢弃余数)
# power--对于第一个数组中的元素A,根据第二个数组中的相应的元素B,计算A**B
# maximum,fmax--元素级的最大值计算,fmax将忽略NAN
# minimum,fmin--元素级的最小值计算,fmin将忽略NAN
# mod--元素级的取模计算(除法的余数)余数。
# copysign--将第二个数组中的符号复制给第一个数组中的值
# greater、greater_equal、less、less_equal、equal、not equal--执行数组元素的比较运算,产生布尔型数组。相当于中辍运算符 >,>=,<,<=,==,!=
# logical_and、logical_or、logical_xor--执行元素级的真值逻辑运算。相当于中辍运算符 &、|、^
#示例:
arr=np.arange(10)
np.sqrt(arr) np.exp(arr)
arrfloat=np.random.randn(7)*5
np.modf(arrfloat) # 返回两个数组
arr1=np.random.randn(8) arr2=np.random.randn(8)
np.add(arr1,arr2) np.maximum(arr1,arr2)
# 11,面向数组编程
# 1) np.meshgrid(arr1,arr2) 生成网格点坐标矩阵
# 假设我们想得到一组值(网格型)上计算sqrt(x^2+y^2)。np.meshingrid(arr1,arr2)函数接受两个一维数组,并产生两个二维矩阵
# 假设一维数组的长度为n,那么二维数组的shape为(n,n)
#(对应于两个数组中所有的(x,y)对):
import numpy as np
points=np.arange(-5,5,0.01) # 一维数组
xs,ys=np.meshgrid(points,points) # xs,ys均为二维数组,两个数组互为转置关系
z=np.sqrt(xs**2+ys**2) # xs**2+ys**2是数组间的运算得到一个新数组 然后再sqrt
import matplotlib.pyplot as plt
plt.imshow(z,cmap=plt.cm.gray);plt.colorbar() # 作图
plt.title("Image plot of $\sqrt{x^2+y^2})$ for a grid of values")
# 2) np.where(boolarr或返回布尔数组的表达式,arr1或标量1,arr2或标量2)
# 返回一个数组
xarr=np.array([1.1,1.2,1.3,1.4,1.5])
yarr=np.array([2.1,2.2,2.3,2.4,2.5])
condarr=np.array([True,False,True,True,False])
np.where(condarr,xarr,yarr)
arrrandn = np.random.randn(4,4)
new_arr = np.where(arrrandn>0,2,-2) # np.where()常用于根据一个数组 arrrandn,而生成另一个新数组 new_arr。
arrrandn = np.random.randn(4,4)
new_arr = np.where(arrrandn>0,2,arr) # 大于0的元素赋值为2,其他元素依然是arr对应的元素(即其他元素不变)。
# -------------------------这部分可不看--------------------------
# np.where(boolarr或返回布尔数组的表达式) 没搞明白存在的意义
# 返回元组
import numpy as np
a = np.array([1,3,5,7,9])
arr=np.where(a>5) # (array([3, 4], dtype=int64),) 是【元组】
arr2=a[arr,] # 等同于 a[arr] 返回:array([[7, 9]]) 一个二维数组
arr2.ndim # 2
arr2.shape # (1,2)
a[a>5] # array([7, 9]) # 一维数组,这可能才是我们想要的。
arr01=np.array([[7,9]]) # array([[7, 9]])
arr01.ndim # 2
arr01.shape # (1, 2)
# --------------------------------------------------------------
# numpy.where的嵌套使用:
# 两个布尔类型的数组cond1和cond2,如果对应元素都是True,就是11,如果只有第一个数组的元素是True,就是10,
# 如果只有第二个数组的元素是True,就是01,如果两个数组的对应元素都是False元,就是00,用列表接收他们。
results=[]
arr1=np.array([True,False,False,False,True])
arr2=np.array([False,False,True,False,True])
n=arr1.size
for i in range(n):
if arr1[i] and arr2[i]:
results.append('11')
elif arr1[i]:
results.append('10')
elif arr2[i]:
results.append('01')
else:
results.append('00')
results
# 使用np.where进行嵌套就可以写得更简单:
np.where((arr1 & arr2),'11',np.where(arr1,'10',np.where(arr2,'01','00'))).tolist()
# 12,数学和统计方法 聚合函数和其他函数
# 可以作为数组的实例方法被调用,也可以作为顶级numpy函数使用
# 聚合函数:
# sum 沿着轴向计算所有的累计和,0长度的数组,累计和就是0
# mean 数学平均,0长度的数组平均值是 NAN
# std 标准差,可以选择自由度调整(默认分母是 n)
# var 方差,可以选择自由度调整(默认分母是 n)
# min,max 最小值和最大值
# argmin,argmax 最小值和最大值的位置
# 其他统计方法:
# cumsum 所有元素的累积和,第一个加数为0
# cumprod 所有元素的累积,第一个乘数是1
# 这两个函数不会使数组聚合,而是会产生一个中间结果的数组。
# 示例:
arr=np.random.randn(5,4)
print(arr.mean(),"--",np.mean(arr)) # 整个数组的平均值
print(arr.mean(1),"--",np.mean(arr,1)) # 每行的平均值
print(arr.mean(0),"--",np.mean(arr,0)) # 每列的平均值
print(arr.sum(axis=1),"--",np.sum(arr,axis=1)) # 计算每一列的和
print(arr.std(axis=1),"--",np.std(arr,axis=1)) # 计算每一列的标准差
# 对一维数组的某个轴数据使用cumsum,umprod:
arr1=np.array([1,2,3,4,5,6,7])
arr1.cumsum() # array([1, 3, 6, 10, 15, 21, 28], dtype=int32) 等同 np.cumsum(arr1)
arr1.cumprod() # array([ 1, 2, 6, 24, 120, 720, 5040], dtype=int32) 等同 np.cumprod(arr1)
# 对二维数组的某个轴数据使用cumsum,umprod:
arr3=np.arange(9).reshape((3,3))
arr3
# 13,操作布尔值数组的方法 sum(),any(),all()
# sum(),any(),all() 既可以作为数组实例的方法被调用,也可以作为顶级numpy函数使用。
# 这些函数用于非布尔类型数组,所有非 0元素,都会被认为是True.
# sum()
arr=np.random.randn(100)
print((arr>0.1).sum()) # 统计数组中元素大于0.1的个数 布尔类型数组的True相当于1,False相当于0 等同于 print(np.sum(arr>0.1))
# any()和all(), any检查数组中是否至少有一个True,all检查数组中是否全是True, 返回布尔类型的值
bools=np.array([False,True,False,False])
print(bools.any()) # True print(np.any(bools))
print(bools.all()) # False print(np.all(bools))
# 14, 数组排序 arr.sort() 会改变原数组; np.sort(arr)返回数组的copy,不会改变原数组。
# arr.sort()对一维数组排序:
arr=np.random.randn(6)
arr # array([-1.5197868 , 0.70317138, -1.32870498, -0.79815157, 0.44850826, 0.84079777])
arr.sort() # 不返回值,原数组改变。
arr # array([-1.5197868 , -1.32870498, -0.79815157, 0.44850826, 0.70317138,0.84079777])
# np.sort(arr)对一维数组排序:
arr=np.random.randn(6)
arr # array([ 1.69866908, -0.93876399, -2.17448296, 1.18976963, -0.52686091, -0.54713395])
np.sort(arr) # array([-2.17448296, -0.93876399, -0.54713395, -0.52686091, 1.18976963, 1.69866908])
arr # array([ 1.69866908, -0.93876399, -2.17448296, 1.18976963, -0.52686091, -0.54713395]) 原数组未改变
# arr.sort()对于二维数组排序,参数为轴号,缺省时默认为 1(不推荐缺省):
arr2=np.random.randn(5,3)
arr2
arr2.sort() 相当于 arr2.sort(1)
arr2 # 数组改变
np.sort(arr2,1) # 原数组不改变 行数据排序
np.sort(arr2,0) # 原数组不改变 列数据排序
# 15, 一维 ndarray的基础集合操作
# 注,都是numpy的顶层方法,ndarray对象不存在这些方法。
# np.unique(arr) 计算arr的唯一值,并排序
# np.intersect1d(arr1,arr2) 计算两个数组的交集,并排序
# np.union1d(arr1,arr2) 计算两个数组的并集,并排序
# np.ind1d(arr1,arr2) 计算arr1的元素,是否存在于arr2中,返回一个和 arr1长度一致的布尔类型数组
# np.setdifferent(arr1,arr2) 差集,在arr1中,但不在arr2中的元素
# np.setxor1d(arr1,arr2) 异或集,在arr1中或在arr2中,但不在二者的交集中
# 示例 1:np.unique(arr)
names=np.array(['Bob','Joe','Will','Bob','Will','Joe','Joe'])
np.unique(names) # array(['Bob', 'Joe', 'Will'], dtype='<U4')
# 用纯python 来实现上面的例子:
# 使用set()函数,将数组转化为set集合,自动去重,然后用sorted()函数对set集合排序,得到列表:
# 知识点:set(ndarray对象)得到去重后的set集合, sorted(set)得到排序后的列表。
names=np.array(['Bob','Joe','Will','Bob','Will','Joe','Joe'])
names_set=set(names)
sorted(names_set) # ['Bob', 'Joe', 'Will']
# 示例 2:np.in1d(arr1,arr2)
values01=np.array([5,6,7,9,0,0,3])
values02=np.array([5,8,7,5])
np.in1d(values01,values02) # array([ True, False, True, False, False, False, False])
# 16, 使用数组进行文件输入和输出 (忽略)
# Numpy 可以将数据以【文本】或【二进制】的形式存入硬盘,或从硬盘载入。
# 由于大部分用户更倾向于使用pandas等其他工具来载入文本或表格型数据,因此,忽略。
# 17, 线性代数 (对于目前工作用不到,忽略)
# 18, 伪随机数生成 (记住几个常用的随机函数,用来生成测试数组)
# numpy.random 模块填补了python模块的不足,可以高效的生成多种概率分布下的完整样本值数组。
# numpy.random 中的部分函数列表:
# seed 像随机数生成器传递随即状态种子
# permutation 返回一个序列的随机排列,或者返回一个乱序的整数范围序列
# shuffle 随机排列一个序列
# rand 从均匀分布中抽取样本
# randint 根据给定的由低到高的范围抽取随机整数 np.random.randint(start,end,size=n),n是想生成的一维随机数组的大小
# randn 从均值0方差1的正态分布中抽取样本 (MATLAB 型接口)
# binomial 从二项分布中抽取样本
# normal 从正态(高斯)分布中抽取样本
# beta 从beta分布中抽取样本
# chisquare 从卡方分布中抽取样本
# python 中random.randint()用法: random.randint(0,1) 表示从0和1随机选取一个整数,
# random.randint(0,5) 表示从0,1,2,3,4,5中随机选取一个整数
# 如,可以使用normal 来获得一个4x4的正态分布样本数组:
samples=np.random.normal(size=(4,4)) # 注意参数的写法
samples
# 19,综合示例 随机漫步 (见之前的博客)