각 행 집합(다른 열 기반)에서 하나의 행(열 값 기반)을 선택합니다.

각 행 집합(다른 열 기반)에서 하나의 행(열 값 기반)을 선택합니다.

다음 파일이 있습니다.

gene.14977.0.1.p2       NbD023586.1.mrna1       100.0   132     0       0       1       132     1       132     4.9e-72     268.9
gene.14977.0.1.p2       NbD032405.1.mrna1       95.5    132     6       0       1       132     1       132     1.5e-68     257.3
gene.14983.1.1.p1       NbE05064429.1.mrna1     61.4    202     13      3       8       145     530     730     8.6e-51     198.7
gene.14983.1.1.p1       NbD024082.1.mrna1       59.3    209     13      3       8       145     530     737     5.6e-50     196.1
gene.14983.1.1.p1       NbD018021.1.mrna1       59.5    205     18      3       5       145     523     726     3.0e-48     190.3
gene.14986.0.0.p1       NbD007981.1.mrna1       100.0   422     0       0       9       430     1       422     1.8e-256    883.2
gene.14986.0.0.p1       NbD032402.1.mrna1       96.5    430     14      1       1       430     1       429     2.7e-252    869.4
gene.14986.0.0.p1       NbD023991.1.mrna1       85.3    428     61      1       1       428     1       426     2.1e-225    780.0

각 유전자 값(예: 첫 번째 열)에 대해 열 11(예: ) gene.14977.0.1.p2에서 가장 작은 값이 있는 행만 유지하고 싶습니다 . 4.9e-72예상되는 출력은 다음과 같습니다.

gene.14977.0.1.p2       NbD023586.1.mrna1       100.0   132     0       0       1       132     1       132     4.9e-72     268.9
gene.14983.1.1.p1       NbE05064429.1.mrna1     61.4    202     13      3       8       145     530     730     8.6e-51     198.7
gene.14986.0.0.p1       NbD007981.1.mrna1       100.0   422     0       0       9       430     1       422     1.8e-256    883.2

그게 어떻게 가능해?

답변1

11번째 컬럼에서 최소값을 갖는 행을 추출하고 싶다면유전자별로 그룹화그런 다음 유전자 식별자를 연관 배열의 키로 사용하여 awk해당 유전자의 최소값을 추적합니다.

$ awk '{ gene = $1 } min[gene] == "" || min[gene] > $11 { min[gene] = $11; line[gene] = $0 } END { for (gene in line) print line[gene] }' file
gene.14983.1.1.p1       NbE05064429.1.mrna1     61.4    202     13      3       8       145     530     730     8.6e-51 198.7
gene.14977.0.1.p2       NbD023586.1.mrna1       100.0   132     0       0       1       132     1       132     4.9e-72 268.9
gene.14986.0.0.p1       NbD007981.1.mrna1       100.0   422     0       0       9       430     1       422     1.8e-256        883.2

여기서는 각 유전자의 최소값이 나오는 실제 행을 추적하고 마지막에 해당 행을 인쇄합니다.

프로그램 awk의 형식은 다음과 같습니다.

{
        # Pick out the gene name
        gene = $1
}

min[gene] == "" || min[gene] > $11 {
        # This gene hase either not been seen before,
        # or its value in column 11 is smaller than
        # what has been seen before (for this gene).
        min[gene] = $11    # save small value from column 11
        line[gene] = $0    # save whole line
}

END {
        # Print all remembered lines.
        for (gene in line)
                print line[gene]
}

유지 관리하기 어려운 코드를 좋아하는 사람들을 위한 최소화된 한 줄 버전:

awk 'm[$1]==""||m[$1]>$11{m[$1]=$11;t[$1]=$0}END{for(g in t)print t[g]}' file

sortGNU(과학적 표기법으로 숫자를 "인간 숫자 정렬" 수행)를 사용하여 동일한 결과(아마도 다른 순서로)를 얻을 수도 있습니다.

$ sort -k1,1 -k11,11g file | sort -u -k1,1
gene.14977.0.1.p2       NbD023586.1.mrna1       100.0   132     0       0       1       132     1       132     4.9e-72 268.9
gene.14983.1.1.p1       NbE05064429.1.mrna1     61.4    202     13      3       8       145     530     730     8.6e-51 198.7
gene.14986.0.0.p1       NbD007981.1.mrna1       100.0   422     0       0       9       430     1       422     1.8e-256        883.2

여기서 첫 번째 정렬은 행이 유전자(첫 번째 열)별로 정렬되고 각 유전자에 대한 행이 열 11을 기준으로 숫자별로 정렬되도록 데이터를 정렬합니다. 그런 다음 두 번째는 sort각 유전자에 대한 행을 선택합니다( -u이 옵션 덕분에 각 정렬 키에 대해 단일 항목을 요청함). 이 단일 행은 각 유전자의 첫 번째 행이 되며, 열 11에서 가장 작은 값을 갖는 행이 됩니다(첫 번째 행으로 인해 sort).

sort두 번째 프로그램 대신 짧은 프로그램을 사용할 수 있습니다 awk. 이는 대량의 데이터에 대해 조금 더 빠릅니다.

sort -k1,1 -k11,11g file | awk '!seen[$1]++'

관련 정보