파일에 있는 값의 처음 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

한 가지 어려움은 마침표만 소수 구분 기호로 처리하는 것 awk입니다 .awk

질문에 대한 의견에서 요청한 대로 가장 높은 값의 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분명하지 않은 말투다른 코드로 둘러싸인 매크로:

(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% 범위를 제공합니다.

낮은 0 끝점은 영향을 받지 않으므로 n범위 계산 없이 범위를 연산한 다음 형성하여 이 작업을 수행 할 수 있습니다 0..(trunc (* 5 n) 100). 하한 끝점이 0이면 이점이 없습니다.

그러나 두 번째 5번째 백분위수를 얻기 위해 코드를 변경한다고 가정해 보겠습니다. 그러면 범위 산술은 더욱 간단해집니다 (trunc (* 5 (+ 0..n n)) 100). 범위 n에 추가하고 ([0, n)에서 [n, 2n)로 대체) 이전과 같이 5%로 축소합니다. 즉, 5를 곱하고 100으로 자릅니다.0..n

답변3

이것은 예제 파일에서 작동합니다.

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

확실한 것에 관해서는처음 5이를 위해서는 몇 가지 추가 논리가 필요합니다. 이것은 파일의 개행 수에 소수점 이하 자릿수가 0인 0.05를 곱하여 소수점 이하 자릿수를 제거합니다.

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

관련 정보