如何通过Unix对数组中的数字进行排名?

Léo*_* 준영 7 text-processing numeric-data

我在想这样一个返回数组中数字顺序的简单函数是否存在任何名称。我真的很想通过极简主义的方式和基本的 Unix 命令来做这个排名,但除了不太优雅的基本查找和循环之外,我什么也想不起来。假设你有一个数字数组

17 
94 
3 
52 
4 
4 
9
Run Code Online (Sandbox Code Playgroud)

预期输出,其中重复项仅收到相同的 ID;如何处理重复并不重要,所以觉得走捷径:

4 
6 
1 
5 
2 
2 
3        
Run Code Online (Sandbox Code Playgroud)

动机:我今天看到许多用户使用许多不同的方法来解决这个问题,并使用电子表格做了很多手动步骤;所以我开始考虑用极简主义的方式来做这件事。

将排名算法与 Google 的平均排名进行比较

在谷歌电子表格中,=arrayformula(rank.AVG(A:A,A:A,true))你会得到一个基准作为升序,就像第一个预期输出一样

17  5
94  7
3   1
52  6
4   2.5
4   2.5
9   4
Run Code Online (Sandbox Code Playgroud)

在这里你可以看到我的初始排名算法是有偏见的。我认为能够在这里设置数据集位置会有所帮助。

Sté*_*las 11

如果该列表在 a 中file,每行一个,我会执行以下操作:

sort -nu file |
  awk 'NR == FNR {rank[$0] = NR; next}
      {print rank[$0]}' - file
Run Code Online (Sandbox Code Playgroud)

如果它在一个zsh $array

sorted=(${(nou)array})
for i ($array) echo $sorted[(i)$i]
Run Code Online (Sandbox Code Playgroud)

这与上述awk版本的原理相同,排名是数字 ( / ) 有序 ( / )、唯一 ( / ) 元素列表中的索引NR/ 。(i)-n(n)sort(o)-u(u)

对于您的平均排名:

sort -n file |
  awk 'NR == FNR {rank[$0] += NR; n[$0]++; next}
  {print rank[$0] / n[$0]}' - file
Run Code Online (Sandbox Code Playgroud)

这使:

5
7
1
6
2.5
2.5
4
Run Code Online (Sandbox Code Playgroud)

(用于sort -rn反转您的Google 电子表格版本中的顺序)。

  • @Masi,请参阅平均排名的编辑。我不理解你关于 _biased/unbiased_ 和 _dataset location_ 的句子。可能您的问题需要更多上下文。 (2认同)

JJo*_*oao 8

nl x | sort  -k 2n | nl | sort -k 2n | cut -f1
Run Code Online (Sandbox Code Playgroud)

...在重复的情况下,它的行为略有不同:

 nl x | sort  -k 2n | nl | sort -k 2n | cut -f1,3
 5  17 
 7  94 
 1  3 
 6  52 
 2  4 
 3  4 
 4  9
Run Code Online (Sandbox Code Playgroud)


gle*_*man 6

仅使用 GNU awk:

awk '
    FNR == NR {numbers[$1]=1; next} 
    FNR == 1 {
        n = asorti(numbers, sorted, "@ind_num_asc")
        for (i=1; i<=n; i++) rank[sorted[i]] = i
    }
    {print rank[$1]}
' file file
Run Code Online (Sandbox Code Playgroud)

  • 我发现这对我的口味来说太晦涩了,更喜欢赋值来创建数组元素。 (3认同)
  • 请注意,`numbers[$1]=1` 可以简化为`numbers[$1]`,因为您不关心该散列的值。 (2认同)