我想要实现的是一系列值的“从最高到最低”排名,基本上与rankdata相反
所以而不是:
a = [1,2,3,4,3,2,3,4]
rankdata(a).astype(int)
array([1, 2, 5, 7, 5, 2, 5, 7])
我想得到这个:
array([7, 6, 3, 1, 3, 6, 3, 1])
我无法在rankdata文档中找到任何内容来执行此操作。
答案 0 :(得分:7)
可能是你不想要的愚蠢答案,但是你不能只减去长度,即从高等级到低等级的“反向”?
a = [1,2,3,4,3,2,3,4]
len(a) - rankdata(a).astype(int)
array([7, 6, 3, 1, 3, 6, 3, 1])
答案 1 :(得分:2)
另一种方法是将列表变为负数:
>>> from scipy.stats import rankdata
>>> a = [1,2,3,4,3,2,3,4]
>>> rankdata([-1 * i for i in a]).astype(int)
array([8, 6, 4, 1, 4, 6, 4, 1])
我发现这是一种更准确的方法,因为关系的分辨率在倒排的意义上得到了解决,而不是在自然等级的意义上。此外,在这种情况下,最小值将获得列表的最后位置的值,如通常所期望的那样。
答案 2 :(得分:0)
请牢记这两个答案的问题,当您使用argsort时,这将导致顺序不一致,仅在发生联系时才会出现。
例如
a=[1,1,2,3,4]
np.argsort(stats.rankdata(a))=array([0, 1, 2, 3, 4], dtype=int64
np.argsort(stats.rankdata([-1*i for i in a])) = array([4, 3, 2, 0, 1], dtype=int64)
np.argsort(5-stats.rankdata(a))= array([4, 3, 2, 0, 1], dtype=int64)
请注意,反转会导致领带顺序不一致(0和1),不会像原来那样翻转。
答案 3 :(得分:0)
(至少)有两种简单的方法可以做到这一点,但需要考虑一些微妙之处,我将在此过程中指出。
除非原始排名都是整数,否则转换为 int 不是一个好主意,在这种情况下您不需要它! rankdata()
中处理平局的默认方法是 "average"
,如果存在平局,这将导致分数排名。这大概是问题中转换为整数的原因。如果您使用其他方法之一,即 "max"
、"min"
或 "ordinal"
,则排名已经是整数。我将假设这对 OP 来说是可以接受的,并从这里开始使用 method="max"
。
在这种方法中,我们先排名,然后颠倒顺序
len(a) - rankdata(a, method="max") + 1
给出
[8 6 3 1 3 6 3 1]
+ 1
是必需的,因为 rankdata()
返回的最大排名是 len(a)
,但我们希望我们的最低排名永远不会为 0。请注意,即使我们最初使用 {{1 }} 解决关系,我们得到 "max"
行为,由于逆转。例如,两次出现的 2 有效地位于第 6 和第 7 级,并且都被指定为 6,这是这些等级中的最小值,而不是最大值。
这种方法需要遍历列表以将值乘以 -1,这会减慢速度:
"min"
给出
rankdata([-el for el in a], method="max")
在这种情况下,我们确实得到了 array([8, 7, 5, 2, 5, 7, 5, 2])
行为,例如,两次出现的 2 有效地位于第 6 和第 7 级,并且都被分配了 7,这是这些等级中的最大值。这就是导致排名 1 没有出现的原因,因为我们在排名 1 和 2 处有平局,得到排名 2,这是这两个排名中的最大值。
如果您希望在长输入上执行此操作,并且速度是一个问题,那么很明显第一种方法应该更快。例如,如果我们使用输入:
"max"
然后我们得到:
a = numpy.random.randint(100, size=1000).tolist()