Numpy库:排序

1 Numpy库的快速排序: np.sort和np.argsort

  • np.sort默认是快速排序,可以在不修改原始输入数组的基础上返回一个排好序的数组,并且也可设置参数axis,一维数组就不展示了
# 通过axis参数沿着行或列排序, 任何行列关系将丢失

rand = np.random.RandomState(42)
X = rand.randint(0, 10, (3, 3))
print(X)
print('对X的每列排序: \n', np.sort(X, axis = 0))
print('对X的每行排序: \n', np.sort(X, axis = 1))
# 也可以直接对原数组进行排序,即X.sort()

[[6 3 7]
[4 6 9]
[2 6 7]]
对X的每列排序:
[[2 3 7]
[4 6 7]
[6 6 9]]
对X的每行排序:
[[3 6 7]
[4 6 9]
[2 6 7]]

  • np.argsort返回的是原始数组排好序的索引值
x = np.array([2, 1, 4, 3, 5])
i = np.argsort(x)
print(i)

[1 0 3 2 4]

1.2 部分排序: 分隔

  • 有时候我们不希望对整个数组排序,仅仅希望找到数组中最小的K个值,np.partition函数提供了这个功能,np.partiton函数的输入是数组和数字K,输出结果是一个新数组,最左边是最小的K个值,往右是任意顺序的其他值.
  • 类似于argsort, np.partition也有相关的np.argpartition用于返回索引
print(X)
print('每列先返回最小两个值:\n', np.partition(X, 2, axis = 0))
print('每行先返回最小两个值:\n', np.partition(X, 2, axis = 1))
# 一维数组就不呈现了

[[6 3 7 4 6 9]
[2 6 7 4 3 7]
[7 2 5 4 1 7]
[5 1 4 0 9 5]]
每列先返回最小两个值:
[[2 1 4 0 1 5]
[5 2 5 4 3 7]
[6 3 7 4 6 7]
[7 6 7 4 9 9]]
每行先返回最小两个值:
[[3 4 6 7 6 9]
[2 3 4 7 6 7]
[1 2 4 5 7 7]
[0 1 4 5 9 5]]

1.3 示例: K个最近邻(广播和聚合的极致操作,略难,可不看)

  • 以下示例展示如何使用argsort函数沿着多个轴快速找到集合中每个点的最近邻。
# 首先在二维平面上创建一个有10个随机点的集合,按照惯例这些数据点放在一个10X2的数组中
np.random.seed(0)
X = rand.rand(10, 2)
print('X: \n', X)

X:
[[0.5488135 0.71518937]
[0.60276338 0.54488318]
[0.4236548 0.64589411]
[0.43758721 0.891773 ]
[0.96366276 0.38344152]
[0.79172504 0.52889492]
[0.56804456 0.92559664]
[0.07103606 0.0871293 ]
[0.0202184 0.83261985]
[0.77815675 0.87001215]]

  • 现在来计算两两数据点对间的距离,两点间的距离的平方等于每个维度距离差的平方的和,利用广播和聚合功能计算矩阵的平方距离
  • 以下这一步写得很巧妙,它充分体现了广播和聚合的规则.在固定x轴上坐标点的前提下,分别在两种维度(z轴和y轴)上放置这10个坐标,得到了(10×1×2)和(1×10×2).再通过广播,都变成(10×10×2).原数组平方后,再对最后一个轴(zyx),也就是x轴进行求和,便得到了所谓的欧几里得距离矩阵.
dist_sq = np.sum((X[:,np.newaxis,:] - X[np.newaxis,:,:]) **2, axis = -1)
dist_sq.shape
# 确认以上步骤,应该看到该矩阵的对角线(也就是每个点到其自身的距离)都是0
dist_sq.diagonal()

(10, 10)
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])

  • 然后才是排序
# 得到一个转化为两点间的平方距离的矩阵后,就可以使用np.argsort函数沿着每行进行排序,最左边的列给出的索引值就是最近邻
# 需要注意的是,第一列是按照0-9从小到大顺序排列的,这是因为每个点的最近邻是其自身
nearest = np.argsort(dist_sq, axis = 1)
nearest
# 如果使用全排序,我们实际上可以实现的比这个例子展示的更多。如果仅仅关心k个最近邻,那么唯一需要做的是分隔每一行,这样最小的k + 1的平方距离将排在最前面,其他更长距离占据矩阵该行的其他位置。可以用np.argpartition函数实现:
k = 2
nearest_partition = np.argpartition(dist_sq, k + 1, axis = 1)
nearest_partition

array([[0, 3, 9, 7, 1, 4, 2, 5, 6, 8],
[1, 4, 7, 9, 3, 6, 8, 5, 0, 2],
[2, 1, 4, 6, 3, 0, 8, 9, 7, 5],
[3, 9, 7, 0, 1, 4, 5, 8, 6, 2],
[4, 1, 8, 5, 6, 7, 9, 3, 0, 2],
[5, 8, 6, 4, 1, 7, 9, 3, 2, 0],
[6, 8, 5, 4, 1, 7, 9, 3, 2, 0],
[7, 9, 3, 1, 4, 0, 5, 8, 6, 2],
[8, 5, 6, 4, 1, 7, 9, 3, 2, 0],
[9, 7, 3, 0, 1, 4, 5, 8, 6, 2]])
array([[3, 0, 9, 7, 1, 4, 2, 5, 8, 6],
[1, 4, 7, 9, 3, 5, 6, 2, 8, 0],
[2, 1, 4, 6, 3, 0, 5, 7, 8, 9],
[3, 9, 7, 0, 1, 5, 6, 2, 8, 4],
[1, 8, 4, 5, 7, 6, 9, 3, 2, 0],
[5, 8, 6, 4, 1, 7, 9, 3, 2, 0],
[6, 8, 5, 4, 1, 7, 9, 3, 2, 0],
[7, 9, 3, 1, 4, 5, 6, 2, 8, 0],
[8, 5, 6, 4, 1, 7, 9, 3, 2, 0],
[3, 9, 7, 0, 1, 5, 6, 2, 8, 4]])

  • 可视化
# 为了将邻节点网络可视化,我们将每个点和其最近的两个最近邻连接
import matplotlib.pyplot as plt
import seaborn; seaborn.set # 设置绘图风格

plt.scatter(X[:, 0], X[:, 1], s = 100)

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')

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值