一、NUMPY修改数组
1.分析脚本内各函数用时占比:%prun;
2.非副本视图的子数组修改
numpy中视图和副本的区别_u014157109的博客-CSDN博客
import numpy as np
x2=np.array([(12,5,2,4),(7, 6, 8, 8),(1, 6, 7, 7)])
print(x2)
x2_sub = x2[:2, :2]
x2_sub[0, 0] = 99
print(x2)
---------------------------------------------------------------
[[12 5 2 4]
[ 7 6 8 8]
[ 1 6 7 7]]
[[99 5 2 4]
[ 7 6 8 8]
[ 1 6 7 7]]
优点:在处理非常大的数据集时,可以获取或处理这些数据集的片段,而不用复制底层的数据缓存。
3.数组变形
grid1= np.arange(1, 13).reshape((4, 3))
grid=grid1.reshape((2, 6))
grid
------------------------------
array([[ 1, 2, 3, 4, 5, 6],
[ 7, 8, 9, 10, 11, 12]])
4.数组拼接和分裂
沿着固定维度处理数组时,适合使用 np.vstack(垂直栈)和 np.hstack(水平栈)函数
#拼接
x = np.array([1, 2, 3])
grid = np.array([[9, 8, 7], [6, 5, 4]])
# 垂直栈数组
np.vstack([x, grid])
----------------------------------
array([[1, 2, 3],
[9, 8, 7],
[6, 5, 4]])
==================================
# 水平栈数组
y = np.array([[99], [99]])
np.hstack([grid, y])
----------------------------------
array([[ 9, 8, 7, 99],
[ 6, 5, 4, 99]])
可通过 np.split、np.hsplit 和 np.vsplit 函数来分裂。可以向以上函数传递一个索引列表作为参数,索引列表记录的是分裂点位置:
#分裂
一维:
x = [1, 2, 3, 99, 99, 3, 2, 1]
x1, x2, x3 = np.split(x, [3, 5])
print(x1, x2, x3)
----------------------------------
[1 2 3] [99 99] [3 2 1]
==================================
多维横切:
grid=np.array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
upper, lower = np.vsplit(grid, [2])
print(upper,'\n',lower)
----------------------------------
[[0 1 2 3]
[4 5 6 7]]
[[ 8 9 10 11]
[12 13 14 15]]
==================================
多维竖切:
left, right = np.hsplit(grid, [2])
print(left,'\n',right)
----------------------------------
[[ 0 1]
[ 4 5]
[ 8 9]
[12 13]]
[[ 2 3]
[ 6 7]
[10 11]
[14 15]]
二、NUMPY数组计算——通用函数
向量操作
运算符 | 描述 |
+、-、*、/ | 加减乘除 |
// | 地板除法运算(3//2=1) |
** | 指数 |
% | 余数 |
通用函数高级特性
1.指定输出
在进行大量运算时,有时候指定一个用于存放运算结果的数组是非常有用的。不同于创建临时数组,你可以用这个特性将计算结果直 接写入到你期望的存储位置。所有的通用函数都可以通过 out 参数来指定计算结果的存放位置:
这个特性也可以被用作数组视图,例如可以将计算结果写入指定数组的每隔一个元素的位置:
x = np.array([0,1,2,3,4])
y = np.empty(5)
np.multiply(x, 10, out=y)
print(y)
--------------------------
[ 0. 10. 20. 30. 40.]
==========================
y = np.zeros(10)
np.power(2, x, out=y[::2])#切片,步长为2
print(y)
--------------------------
[ 1. 0. 2. 0. 4. 0. 8. 0. 16. 0.]
2.聚合(或者说递归)
二元通用函数有些非常有趣的聚合功能,这些聚合可以直接在对象上计算。例如,如果我们希望用一个特定的运算 reduce一个数组,那么可以用任何通用函数的 reduce 方法。一个reduce方法会对给定的元素和操作重复执行,直至得到单个的结果。
x = np.arange(1, 6)
np.add.reduce(x)
------------------------
15
========================
#如果需要存储每次计算的中间结果,可以使用 accumulate:
np.add.accumulate(x)
------------------------
array([ 1, 3, 6, 10, 15])
三、NUMPY数组计算——聚合
函数名 | NaN安全版本 | 描述 |
np.sum | np.nansum | 求和 |
np.prod | np.nanprod | 求积 |
np.mean | np.nanmean | 平均值 |
np.std | np.nanstd | 标准差 |
np.var | np.nanvar | 方差 |
np.min | np.nanmin | 最小值 |
np.max | np.nanmax | 最大值 |
np.argmin | np.nanargmin | 最小值的索引 |
np.argmax | np.nanargmax | 最大值的索引 |
np.median | np.nanmedian | 求中位数 |
np.percentile | np.nanpercentile | 求xx分位的值 |
np.any | 验证任一元素是否为真 | |
np.all | 验证所有元素是否为真 |
四、NUMPY数组计算——广播
1.广播的介绍
广播允许二进制操作用于不同大小的数组。例如,可以将一个标量(可认为是一个零维的数组)和
一个数组相加:
a = np.array([0, 1, 2])
M = np.ones((3, 3))
a+M
---------------------------------
array([[1., 2., 3.],
[1., 2., 3.],
[1., 2., 3.]])
这里这个一维数组就被扩展或者广播了。它沿着第二个维度扩展,扩展到匹配M数组的形状。这个例子理解起来很容易,更复杂的情况会涉及对两个数组 的同时广播,例如以下示例:
a = np.arange(3)
b = np.arange(3)[:, np.newaxis]
print(a)
print(b)
a+b
-----------------------------------
[0 1 2]
[[0]
[1]
[2]]
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4]])
2.广播的规则
规则 1:如果两个数组的维度数不相同,那么小维度数组的形状将 会在最左边补 1。
规则 2:如果两个数组的形状在任何一个维度上都不匹配,那么数组的形状会沿着维度为 1 的维度扩展以匹配另外一个数组的形状。
规则 3:如果两个数组的形状在任何一个维度上都不匹配并且没有 任何一个维度等于 1,那么会引发异常。
3.广播的应用
a.数组归一化
假设你有一个有 10 个观察值的数组,每个观察值包含 3 个数值。按照惯例,我们将用一个 10×3 的数组存放该数据:
X = np.random.random((10, 3))
Xmean = X.mean(0)#0表示按列求平均,1表现按行
X_centered = X - Xmean
print(X,'\n'*2,Xmean,'\n'*2,X_centered,'\n'*2,X_centered.mean(0))
------------------------------------------------------------
[[0.56796257 0.38069875 0.24609822]
[0.28636813 0.44924361 0.16596211]
[0.34745014 0.96413453 0.10129919]
[0.15104245 0.31396111 0.13444006]
[0.54375014 0.95257405 0.1685155 ]
[0.88164314 0.52867621 0.40352841]
[0.33418199 0.66096983 0.00824594]
[0.2773684 0.76373737 0.62178445]
[0.42070625 0.51417225 0.23095697]
[0.25618902 0.64738883 0.90916247]]
[0.40666622 0.61755565 0.29899933]
[[ 0.16129635 -0.23685691 -0.05290111]
[-0.12029809 -0.16831205 -0.13303722]
[-0.05921608 0.34657887 -0.19770014]
[-0.25562378 -0.30359455 -0.16455927]
[ 0.13708392 0.3350184 -0.13048383]
[ 0.47497692 -0.08887944 0.10452907]
[-0.07248424 0.04341417 -0.2907534 ]
[-0.12929783 0.14618172 0.32278512]
[ 0.01404003 -0.10338341 -0.06804236]
[-0.1504772 0.02983318 0.61016314]]
[-2.22044605e-17 2.22044605e-17 0.00000000e+00]
b.二维函数作图
广播另外一个用处在于能基于二维函数显示图像:定义函数 z = f (x, y),可用广播沿着数值区间计算该函数:
np.newaxis作用_Voyege-Class的博客-CSDN博客_np.newaxis
# x和y表示0~5区间50个步长的序列
x = np.linspace(0, 5, 50)
y = np.linspace(0, 5, 50)[:, np.newaxis]
z = np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)
%matplotlib inline
import matplotlib.pyplot as plt
plt.imshow(z, origin='lower', extent=[0, 5, 0, 5],cmap='viridis')
plt.colorbar();
五、NUMPY数组——花哨的索引
X = np.array([[0,1,2,3],[4,5,6,7],[8,9,10,11]])
row = np.array([0, 1, 2])
col = np.array([2, 1, 3])
X[row, col]
------------------------------------------------
array([ 2, 5, 11])
1.示例:选择随机点
这种方法通常用于快速分割数据,即需要分割训练 / 测试数据集以验证统计模型时,以及在解答统计问题时的抽样方法中使用。
rand = np.random.RandomState(42)#随机种子42
mean = [0, 0] #均值
cov = [[1, 2],[2, 5]]#协方差矩阵
X = rand.multivariate_normal(mean, cov, 100)#100个符合正态分布的数
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn;
seaborn.set() # 设置绘图风格
plt.scatter(X[:, 0], X[:, 1]);
indices = np.random.choice(X.shape[0], 20, replace=False)
selection = X[indices]
plt.scatter(X[:, 0], X[:, 1], alpha=0.3)
plt.scatter(selection[:, 0], selection[:, 1],
facecolor='none', edgecolor='b', s=200);
2.示例:数据区间划分
可以用索引将数据进行区间划分并手动创建直方图。例如,假定我们有 1000 个值,希望快速统计分布在每个区间中的数据频次,可以用 ufunc.at 来计算:
np.random.seed(42)
x = np.random.randn(100)
# 手动计算直方图
bins = np.linspace(-5, 5, 20)
counts = np.zeros_like(bins)
# 为每个x找到合适的区间
#在数组bins中插入数组x(并不执行插入操作),返回一个下标列表,这个列表指明了x中对应元素应该插入在bins中哪个位置上
i = np.searchsorted(bins, x)
# 为每个区间加上1
np.add.at(counts, i, 1)
# 画出结果
plt.bar(bins, counts)
当然,如果每次需要画直方图你都这么做的话,也是很不明智的。这就 是为什么 Matplotlib 提供了 plt.hist() 方法,该方法仅用一行代码就 实现了上述功能:
plt.hist(x, bins, histtype='step');
六、NUMPY数组——数组排序
结果排序,默认从小到大:np.sort()
结果排序,获取索引(从小到大):np.argsort
不排序,找到第K小的值:np.partition
x = np.array([7, 2, 3, 1, 6, 5, 4])
np.partition(x, 3)
------------------------------------
array([2, 1, 3, 4, 6, 5, 7])
====================================
x = np.array([7, 2, 3, 1, 6, 5, 4])
i=6
a=np.partition(x,i)
print(a)
print(a[i-1])
------------------------------------
[2 1 3 4 5 6 7]
6
1.示例:K个最近邻