# NumPy中的快速排序:np.sort和np.argsort
# 默认情况下,np.sort 的排序算法是快速排序,
# 其算法复杂度为 O[N log N],另外也可以选择归并排序和堆排序。
# 如果想在不修改原始输入数组的基础上返回一个排好序的数组,可以使用np.sort
import numpy as np
x = np.array([2,1,4,3,5])
np.sort(x)
# 如果希望用排好序的数组替代原始数组,可以使用数组的 sort 方法:
x.sort()
print(x)
# argsort函数返回的是原始数组排好序的索引值:
x = np.array([2,1,4,3,5])
i = np.argsort(x)
print(i)
# 这些索引值可以被用于(通过花哨的索引)创建有序的数组:
x[i]
# NumPy 排序算法的一个有用的功能是通过 axis 参数,沿着多维数组的行或列进行排序
rand = np.random.RandomState(42)
X =rand.randint(0,10,(4,6))
print(X)
np.sort(X,axis=0) #对X的每一列排序
np.sort(X,axis=1) #对X的每一行排序
#这种处理方式是将行或列当作独立的数组,任何行或列 的值之间的关系将会丢失!
#部分排序:分隔
#有时候我们不希望对整个数组进行排序,
#仅仅希望找到数组中第 K小的值,NumPy的np.partition函数提供了该功能。
#np.partition函数的输入是数组和数字 K,
#输出结果是一个新数组,最左边是第 K小的值,往右是任意顺序的其他值:
x = np.array([7,2,3,1,6,5,4])
np.partition(x,3)
#结果数组中前三个值是数组中最小的三个值,剩下的位置是原始数组剩下的值。
#在这两个分隔区间中,元素都是任意排列的。
#也可以沿着多维数组任意的轴进行分隔
np.partition(X,2,axis=1)
#输出结果是一个数组,该数组每一行的前两个元素是该行最小的两个值,
#每行的其他值分布在剩下的位置
#示例:K个最近邻
#示例展示的是如何利用 argsort 函数沿着多个轴快速找到集合中每个点的最近邻
#首先,在二维平面上创建一个有 10 个随机点的集合。
#按照惯例,将这些数据点放在一个 10×2 的数组中:
X = rand.rand(10,2) #以给定的形状创建一个数组,并在数组中加入在[0,1]之间均匀分布的随机样本。
#画出散点图
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn; seaborn.set() # 设置画图风格
plt.scatter(X[:, 0], X[:, 1], s=100);
# 计算两两数据点对间的距离。
dist_sq = np.sum((X[:,np.newaxis,:]-X[np.newaxis,:,:]) ** 2,axis=-1)#计算矩阵的平方距离
#在坐标系中计算每对点的差值
X[:,np.newaxis,:].shape #(10,1,2)
X[np.newaxis,:,:].shape #(1,10,2)
differences = X[:,np.newaxis,:].shape - X[np.newaxis,:,:]
differences.shape #(10,10,2)
#求出差值的平方
sq_differences = differences ** 2
sq_differences.shape
#将差值求和获得平方距离
dist_sq = sq_differences.sum(-1)
dist_sq.shape
dist_sq.diagonal() #该矩阵对角线的值
nearest = np.argsort(dist_sq,axis=1)
print(nearest)
#当我们有了这样一个转化为两点间的平方距离的矩阵后,
#就可以使用 np.argsort 函数沿着每行进行排序了。
#最左边的列给出的索引值就是最近邻:
#第一列是按 0~9 从小到大排列的。这是因为每个点的最近邻是其自身
#如果 我们仅仅关心 k 个最近邻,那么唯一需要做的是分隔每一行,
#这样最小的 k + 1 的平方距离将排在最前面,其他更长的距离占据矩阵该行的其他位置。
K = 2
nearest_partition = np.argpartition(dist_sq,K + 1,axis=1)
# 为了将邻节点网络可视化,我们将每个点和其最近的两个最近邻连接
plt.scatter(X[:,0],X[:,1],s=100) # X[:,0]就是取所有行的第0个数据, X[:,1] 就是取所有行的第1个数据。
#将每个点与它的两个最近邻连接
K = 2
for i in range(X.shape[0]):
for j in nearest_partition[i,:K+1]:
#画一条从X[i]到X[j]的线段
#用zip方法实现:
plt.plot(*zip(X[j],X[i]),color='black')