打印文件中前 5% 的值

打印文件中前 5% 的值

我想在第二列中打印最高 5% 的值,我可以在 Excel 中执行此操作,但我想将前 5% 的值打印到新文件中。我搜索过类似的问题,但我可以找到仅打印前 5 个值的建议。感谢您的时间和帮助。

谢谢你 kp

file.txt

X1 h
382 15325,3
385 15446,4
386 16501,5
446 16480
460 16467,7
534 16437,2
762 16433,7
779 16400,6
783 16398
828 16376,4
918 16319,4

x2 H   
52214 3966,33
52291 3993,4
53165 3500,57
53684 3071,67
54902 2169,83
54921 1968,9
55457 1943,98
55458 903,539
55459 609,993
55460 621,414
55461 553,236
55470 535,005
55472 298,251
55473 298,251
55474 298,251
55475 302,34
55559 371,47
55614 466,165
55679 406,352
55735 426,36

X3 H 
191773 178,645
191775 183,613
191780 193,663
191820 202,933
191838 188,988
191845 175,414
191867 167,791
191880 166,49
191883 170,456
191895 165,781
191900 154,362
191902 177,768
191914 175,431
191916 168,532
191918 163,291
191919 170,911

预期产出(前 5%)

386 16501,5
446 16480

答案1

一个困难awkawk仅处理句点作为小数分隔符。

要报告至少为最高值 95% 的值(按照您对自己问题的评论中的要求),您可以执行以下操作:

awk '{v = $2; gsub(",", ".", v); v += 0}
     !second_pass {
        if (v >= max || !started) {max = v; started=1}
        next
     }
     v >= 95 * max / 100' file second_pass=1 file

这使:

386 16501,5
446 16480
460 16467,7
534 16437,2
762 16433,7
779 16400,6
783 16398
828 16376,4
918 16319,4

如果您想要前 5% 的具有最高值的行(我希望您希望忽略那些不包含类似值的行X3 H),我想我会使用perl它。

perl -lane 'if ($F[1] =~ /\d/) {push @v, ($F[1] =~ y/,/./r); push @l, $_}
            END {
              print for (map {$l[$_]}
                        sort {$v[$b] <=> $v[$a]}
                        (0..$#v))[0..($#v+1)*5/100-1]
            }' file

这使:

386 16501,5
446 16480

答案2

TXR口齿不清awk宏,被其他代码包围:

(let* ((data (build
               (awk ((set rec (regsub #/,/ "." rec))
                     (fconv - r))
                 ([f 1] (add (list [f 1] orec))))))
       (n (length data)))
  (mapdo (opip second put-line)
         [[sort data > first] (trunc (* 5 0..n) 100)]))

传奇:let*,build,awk,rec,orec,fconv,mapdo,opip

跑步:

$ txr top5.tl file.txt
386 16501,5
446 16480

这表明当 Awk 范例是 Lisp 宏时,它可以轻松地嵌入到其他结构中。这里它出现在一个build表单内,该表单建立了构建列表的环境。(add ...)里面的宏添加到一个隐藏列表,该列表在执行完成(内部工作完成)build时返回。(build ...)awk

我们建立的列表是一个对的列表。每对的第一个元素是浮点值。第二个元素是一个字符串:从orec变量获得的原始 awk 记录的逐字记录。当我们对数据进行排序时,我们使用每对的第一个元素作为排序键,并通过函数使用降序>。当我们打印排序数据的前 5% 时,我们通过功能管道映射它(opip second put-line),该管道选择每对的第二个元素(原始记录)并将其传递给put-line.

该表达式(trunc (* 5 0..n) 100)利用了新的 TXR 功能:即范围支持算术。我们采用代表整个数据列表跨度的范围0..n,并将该范围乘以 5,然后除(使用截断整数除法)100。这给出了从 0 到 5% 的范围。

由于较低的零端点不受影响,因此我们可以通过操作n然后形成一个范围来完成此操作,而无需范围算术:0..(trunc (* 5 n) 100)。当下端点为零时,没有任何优势。

但是,假设我们想要更改代码以获得第二个 5 个百分位数。那么范围算术就更简单了:(trunc (* 5 (+ 0..n n)) 100)。我们只需添加n0..n范围(将其从 [0, n) 替换为 [n, 2n)),然后像以前一样缩小到 5%:乘以 5,截断 100。

答案3

这适用于示例文件

sort -gk 2,2 file.txt | tail -n2
446 16480
386 16501,5

至于确定前5这需要一些额外的逻辑。这将获取文件中的换行数并将其乘以 0.05,小数位数为 0 以消除小数。

sort -gk 2,2 file | tail -n$(bc <<<"scale=0; ($(wc -l < file)*.05)/1" | cut -d\. -f1)
446 16480
386 16501,5

相关内容