排列二维 Numpy 数组
Ranking 2D Numpy array
我有一个 1000 行和 2 列的 numpy 数组:
[[ 0.76 1.28947368]
[ 0.7 0.97142857]
[ 0.7 1.48571429]
[ 0.68 1.11764706]
[ 0.68 1.23529412]
[ 0.68 1.41176471]
[ 0.68 1.41176471]
[ 0.68 1.44117647]
[ 0.66 0.78787879]
[ 0.66 1.03030303]
[ 0.66 1.09090909]
[ 0.66 1.15151515]
[ 0.66 1.15151515]
[ 0.66 1.21212121]
[ 0.66 1.24242424]]
很明显,这个数组按第 0 列降序排序,按第 1 列升序排序。我想为这个数组的每一行分配等级,这样重复的行(两列或更多列中的值行相等)具有与第 2 列相同的等级和插入等级。
预期输出:
[[0.76 1.28947368 1]
[ 0.7 0.97142857 2]
[ 0.7 1.48571429 3]
[ 0.68 1.11764706 4]
[ 0.68 1.23529412 5]
[ 0.68 1.41176471 6]
[ 0.68 1.41176471 6] # as this row is duplicate of row above it
[ 0.68 1.44117647 7]
[ 0.66 0.78787879 8]
[ 0.66 1.03030303 9]
[ 0.66 1.09090909 10]
[ 0.66 1.15151515 11]
[ 0.66 1.15151515 11] # as this row is duplicate of row above it
[ 0.66 1.21212121 12]
[ 0.66 1.24242424 13]]
实现此目标的最有效方法是什么?
对于排序数组,就像在给定的示例中一样,它很容易 -
rank = np.r_[True, (a[1:] != a[:-1]).any(1)].cumsum()
out = np.column_stack(( a, rank ))
作为 (a[1:] != a[:-1]).any(1)
的替代方案,我们可以使用以下内容来提高性能:
(a[1:,0] != a[:-1,0]) | (a[1:,1] != a[:-1,1])
分步示例 运行
1) 输入数组:
In [70]: a
Out[70]:
array([[ 0.76 , 1.28947368],
[ 0.68 , 1.41176471],
[ 0.68 , 1.41176471],
[ 0.68 , 1.44117647],
[ 0.66 , 1.09090909],
[ 0.66 , 1.15151515],
[ 0.66 , 1.15151515],
[ 0.66 , 1.24242424]])
2) 获取连续行之间不等式的掩码。这里的想法是,由于数组是排序的,所以重复的行在两列中将具有相同的元素。因此,由于两列之间的不等式,我们将有一个 1D 掩码,但一个元素比原始数组中的总行数少,因为我们使用切片时留下一个元素:
In [71]: a[1:] != a[:-1]
Out[71]:
array([[ True, True],
[False, False],
[False, True],
[ True, True],
[False, True],
[False, False],
[False, True]], dtype=bool)
In [72]: (a[1:] != a[:-1]).any(1)
Out[72]: array([ True, False, True, True, True, False, True], dtype=bool)
现在,为了补偿少一个元素,并且由于我们需要从 1
开始排名,并且我们打算对这个增量排名使用累积求和,让我们在 1
处附加一个 1
开始然后使用 cumsum
给我们预期的排名:
In [75]: np.r_[True, (a[1:] != a[:-1]).any(1)]
Out[75]: array([ True, True, False, True, True, True, False, True], dtype=bool)
In [76]: np.r_[True, (a[1:] != a[:-1]).any(1)].cumsum()
Out[76]: array([1, 2, 2, 3, 4, 5, 5, 6])
为了直观地验证,这里是堆叠输出:
In [77]: np.column_stack(( a, _ ))
Out[77]:
array([[ 0.76 , 1.28947368, 1. ],
[ 0.68 , 1.41176471, 2. ],
[ 0.68 , 1.41176471, 2. ],
[ 0.68 , 1.44117647, 3. ],
[ 0.66 , 1.09090909, 4. ],
[ 0.66 , 1.15151515, 5. ],
[ 0.66 , 1.15151515, 5. ],
[ 0.66 , 1.24242424, 6. ]])
我有一个 1000 行和 2 列的 numpy 数组:
[[ 0.76 1.28947368]
[ 0.7 0.97142857]
[ 0.7 1.48571429]
[ 0.68 1.11764706]
[ 0.68 1.23529412]
[ 0.68 1.41176471]
[ 0.68 1.41176471]
[ 0.68 1.44117647]
[ 0.66 0.78787879]
[ 0.66 1.03030303]
[ 0.66 1.09090909]
[ 0.66 1.15151515]
[ 0.66 1.15151515]
[ 0.66 1.21212121]
[ 0.66 1.24242424]]
很明显,这个数组按第 0 列降序排序,按第 1 列升序排序。我想为这个数组的每一行分配等级,这样重复的行(两列或更多列中的值行相等)具有与第 2 列相同的等级和插入等级。
预期输出:
[[0.76 1.28947368 1]
[ 0.7 0.97142857 2]
[ 0.7 1.48571429 3]
[ 0.68 1.11764706 4]
[ 0.68 1.23529412 5]
[ 0.68 1.41176471 6]
[ 0.68 1.41176471 6] # as this row is duplicate of row above it
[ 0.68 1.44117647 7]
[ 0.66 0.78787879 8]
[ 0.66 1.03030303 9]
[ 0.66 1.09090909 10]
[ 0.66 1.15151515 11]
[ 0.66 1.15151515 11] # as this row is duplicate of row above it
[ 0.66 1.21212121 12]
[ 0.66 1.24242424 13]]
实现此目标的最有效方法是什么?
对于排序数组,就像在给定的示例中一样,它很容易 -
rank = np.r_[True, (a[1:] != a[:-1]).any(1)].cumsum()
out = np.column_stack(( a, rank ))
作为 (a[1:] != a[:-1]).any(1)
的替代方案,我们可以使用以下内容来提高性能:
(a[1:,0] != a[:-1,0]) | (a[1:,1] != a[:-1,1])
分步示例 运行
1) 输入数组:
In [70]: a
Out[70]:
array([[ 0.76 , 1.28947368],
[ 0.68 , 1.41176471],
[ 0.68 , 1.41176471],
[ 0.68 , 1.44117647],
[ 0.66 , 1.09090909],
[ 0.66 , 1.15151515],
[ 0.66 , 1.15151515],
[ 0.66 , 1.24242424]])
2) 获取连续行之间不等式的掩码。这里的想法是,由于数组是排序的,所以重复的行在两列中将具有相同的元素。因此,由于两列之间的不等式,我们将有一个 1D 掩码,但一个元素比原始数组中的总行数少,因为我们使用切片时留下一个元素:
In [71]: a[1:] != a[:-1]
Out[71]:
array([[ True, True],
[False, False],
[False, True],
[ True, True],
[False, True],
[False, False],
[False, True]], dtype=bool)
In [72]: (a[1:] != a[:-1]).any(1)
Out[72]: array([ True, False, True, True, True, False, True], dtype=bool)
现在,为了补偿少一个元素,并且由于我们需要从 1
开始排名,并且我们打算对这个增量排名使用累积求和,让我们在 1
处附加一个 1
开始然后使用 cumsum
给我们预期的排名:
In [75]: np.r_[True, (a[1:] != a[:-1]).any(1)]
Out[75]: array([ True, True, False, True, True, True, False, True], dtype=bool)
In [76]: np.r_[True, (a[1:] != a[:-1]).any(1)].cumsum()
Out[76]: array([1, 2, 2, 3, 4, 5, 5, 6])
为了直观地验证,这里是堆叠输出:
In [77]: np.column_stack(( a, _ ))
Out[77]:
array([[ 0.76 , 1.28947368, 1. ],
[ 0.68 , 1.41176471, 2. ],
[ 0.68 , 1.41176471, 2. ],
[ 0.68 , 1.44117647, 3. ],
[ 0.66 , 1.09090909, 4. ],
[ 0.66 , 1.15151515, 5. ],
[ 0.66 , 1.15151515, 5. ],
[ 0.66 , 1.24242424, 6. ]])