각 고유 항목의 최대값과 최소값을 계산하는 방법

각 고유 항목의 최대값과 최소값을 계산하는 방법

파일에 있는 각 항목의 최대값과 최소값을 찾아야 합니다.

#subset of my file
NEUTRON   20.900103
PION-      0.215176
PION-     22.716532
NEUTRON    8.043279
PION+      1.374297
PION-      0.313350
PION+      0.167848

항목 이름이 여러 개인 경우 파일을 반복하여 각 이름의 최소값과 최대값을 찾는 방법은 무엇입니까? 나는 awk를 사용하여 각 항목의 수를 세었고 중복된 항목은 없지만 각 이름의 각 반복에는 숫자가 포함되어 있으며 그 숫자는 각 항목의 최대값과 최소값에 대해 필터링하려고 하는 것입니다. ex 전체 파일의 출력:

Name         Count     Minimum        Maximum        
--------     -----     ---------      ---------      
KAON-            1      5.489958       5.489958      
NEUTRON          2      8.043279      20.900103      
PHOTON          10      0.034664       1.897264       
PION-            5      0.192247      22.716532       
PION+            7      0.167848       7.631051       
PROTON           1      1.160216       1.160216       

답변1

awk '{
  count[$1]++
  min[$1]=(!($1 in min) || $2<min[$1]) ? $2 : min[$1]
  max[$1]=(!($1 in max) || $2>max[$1]) ? $2 : max[$1]
}
END {
  print "Name","Count","Minimum","Maximum"
  print "----","-----","-------","-------"
  for(i in count) print i,count[i],min[i],max[i]
}' file | column -t

최소 배열 값 할당의 논리는 다음과 같습니다.
첫 번째 필드의 이름이 배열에 존재하지 않는 경우( !($1 in min)) 또는 ( ||) 두 번째 필드가 현재 배열 값( $2<min[$1])보다 작은 경우 ( ?)는 새 값을 할당하고 $2else( :)는 이전 값을 지정합니다 min[$1].

| column -t결과를 표로 예쁘게 인쇄하는 데 사용됩니다 . 필요없으시면 삭제하셔도 됩니다.

산출:

Name     Count  Minimum   Maximum
----     -----  -------   -------
PION+    2      0.167848  1.374297
PION-    3      0.215176  22.716532
NEUTRON  2      8.043279  20.900103

답변2

Jeff Schaller가 지적했듯이 bash는 텍스트 프로세서는 아니지만 요청한 내용은 구현하기가 특별히 어렵지 않습니다. 그래서 여기에 그 일을 할 수 있는 방법이 있습니다. 그만한 가치가 있는 일이죠.

$ awk '!/^#.*/ {
      ((++cnt[$1])); 
      if (cnt[$1]==1) 
          {min[$1]=max[$1]=$2} 
      else if ($2 < min[$1]) 
          { min[$1]=$2} 
      else if ($2 > max[$1]) 
          {max[$1]=$2}
      } 
      END {
          printf "%-10s%7s%10s%12s\n","Name","Count","Minimum", "Maximum";
          for (i in cnt) 
              printf "%-10s%7d%10.6g%12.8g\n", i,cnt[i],min[i],max[i];
          }' testdata 

산출:

Name        Count   Minimum     Maximum
PION+           2  0.167848    1.374297
PION-           3  0.215176   22.716532
NEUTRON         2   8.04328   20.900103

설명하다:

  • 다음으로 시작하는 줄(레코드)을 건너뜁니다.#
  • awk각 레코드에 대해 cnt[$1]은 프로그램 실행 시작 시 0부터 시작하여 1씩 증가됩니다.
  • 현재 레코드의 첫 번째 필드 값 "$1"이 이전에 본 적이 없는 경우 해당 값의 최소값과 최대값을 "$2" 값으로 초기화합니다.
  • 다른 경우(이전 레코드에서 "$1" 값이 한 번 이상 표시되는 경우) 최소값과 최대값을 업데이트합니다.
  • 마지막으로 OP의 예제 출력 측면을 존중하기 위해 형식화된 인쇄를 사용합니다.

관련 정보