我有一个(数百个或数百万个)值的列表,例如:
echo -e "y\ny\ny\nu\ni\no\no\nl\no\nj\nk\nl\nk\nl\nk\nl\nk\nl\nk\nl\no\nu\no\no\nu\ny\nl\ni\nq\nw\ne\nr\nt\na\ns" > list.txt
我想计算每个值在列表中出现的次数,然后选择代表列表中条目的任意部分的最常见值 ( keep
)。我不在乎打破我的实际数据集中的联系。
我当前的工作代码使用sort | uniq | sort
and awk
:
keep=0.50
sort list.txt | uniq -c | sort -nr > temp
awk -v keep=$keep 'NR==FNR {s+=$1}; NR!=FNR {c+=$1; print $0}; c > (s * keep) {exit 0}' temp temp
7 l
6 o
5 k
然而,这两段代码看起来都非常笨拙。有一个更好的方法吗?我无法找到正确的搜索词(因此这个问题的标题很糟糕)。
答案1
您可以使用单个awk
命令(GNU 版本)根据数组包含的值对数组进行唯一排序。是count
一个关联数组,它唯一地计算文件中每一行的出现次数。
这PROCINFO["sorted_in"] = "@val_type_desc"
是一个 GNU构造,它按值的降序对awk
数组中的条目进行排序。count
然后,您对其进行迭代以对出现次数进行求和并打印高频对,直到匹配退出条件。
awk -v keep=0.50 '
{
count[$0]++
}
END {
PROCINFO["sorted_in"] = "@val_type_desc"
for (i in count) {
sum += count[i]
print i, count[i]
if (sum > (NR * keep)) {
break
}
}
}' list.txt