‌첫 번째 열을 ID로 기준으로 각 그룹에서 가장 작은 값을 갖는 행을 선택하는 방법은 무엇입니까?

‌첫 번째 열을 ID로 기준으로 각 그룹에서 가장 작은 값을 갖는 행을 선택하는 방법은 무엇입니까?

다음과 같은 파일이 있습니다.

1   7.8e-12  
1   7.8e-12  
1   1.0e-11   
2   9.3e-13    
2   3.5e-12 
2   3.5e-10
2   3.1e-9         
3   3.0e-11    
3   3.0e-11     
3   1.7e-08   

첫 번째 열의 각 값에 대해 두 번째 열에서 가장 작은 값을 가진 "모든 행"을 선택하고 첫 번째 열을 기준으로 그룹화하고 싶습니다. 따라서 원하는 출력은 다음과 같습니다.

 1   7.8e-12  
 1   7.8e-12
 2   9.3e-13
 3   3.0e-11    
 3   3.0e-11 

이 작업을 수행하는 방법을 아시나요?

답변1

한 가지 방법은 오름차순으로 정렬한 다음 각 col1의 첫 번째 col2 값을 기록하고 현재 col2 값이 동일한지 여부를 인쇄하는 것입니다.

sort -k1,1n -k2,2g file | awk '!a[$1] {a[$1] = $2} $2 == a[$1]'
1   7.8e-12
1   7.8e-12
2   9.3e-13
3   3.0e-11
3   3.0e-11

답변2

과학적 표기법으로 숫자를 처리해야 합니다.

awk '
    NR == FNR {
        if (!($1 in min) || $2 < min[$1])
            min[$1] = $2
        next
    }
    $2 == min[$1]
' file file

파일을 두 번 처리합니다. 한 번은 각 키의 최소값을 찾은 다음 해당 최소값이 있는 행을 출력합니다.

답변3

텍스트 처리 기반 답변을 마무리하기 위해 PostgreSQL을 사용하여 이를 수행하는 방법은 다음과 같습니다.

먼저, 쉽게 가져올 수 있도록 파일을 전처리하여 CSV로 변환합니다.

awk -v OFS=, '$1=$1' file.txt > file.csv

그런 다음 PostgreSQL에서 다음과 같이 임시 테이블을 만듭니다.

create temp table x (id int, bignum float);

CSV를 복사합니다.

\copy x from file.csv with (format csv)

원하는 결과를 얻으려면 임시 테이블을 쿼리하세요.

select id, bignum
from (
  select
    *,
    rank() over (partition by id order by bignum)
      as rank
  from x
) as sqlrequiresthisalias
where rank = 1;

결과:

 id | bignum  
----+---------
  1 | 7.8e-12
  1 | 7.8e-12
  2 | 9.3e-13
  3 |   3e-11
  3 |   3e-11
(5 rows)

답변4

암소 비슷한 일종의 영양awk해결책:

awk 'BEGIN{ PROCINFO["sorted_in"] = "@val_num_asc" }
     { a[$1][++c] = $2 }
     END{ 
         for (i in a) { 
             prev = 0;
             for (j in a[i]) { 
                 v = a[i][j]; if (prev && v != prev) continue; 
                 print i, v; prev = v 
             }
         }
     }' file

산출:

1 7.8e-12
1 7.8e-12
2 9.3e-13
3 3.0e-11
3 3.0e-11

관련 정보