첫 번째 열의 값이 일정/동일한 두 번째 및 세 번째 열의 값을 계산합니다.

첫 번째 열의 값이 일정/동일한 두 번째 및 세 번째 열의 값을 계산합니다.

첫 번째 열의 값이 동일한 탭 구분 txt 파일의 두 번째 및 세 번째 열에서 값/단어 발생 횟수를 계산하고 싶습니다.

입력 파일:

GeneA Pathogenic snp
GeneA Pathogenic snp
GeneA Benign indel
GeneA Likely_pathogenic snp
GeneA Pathogenic    indel
GeneB Benign    snp
GeneB Pathogenic    snp
GeneB Benign    indel
GeneC  Benign   snp
GeneC  Likely_pathogenic    snp

예상 출력: (테이블 형식)

| Pathogenic | Benign | Likely_Pathogenic | snp | indel |
 ------------|--------|-------------------|-----|-------|
|GeneA|     3|       1|                  1|    3|      2|
|GeneB|     1|       2|                  0|    2|      1|
|GeneC|     0|       1|                  1|    2|      0|

답변1

아래 표시된 스크립트는 awk지정된 파일에서 데이터를 수집하고 각 "이름"(첫 번째 열)에서 각 "유형"(두 번째 열 이상)의 발생 횟수를 계산합니다. 모든 입력 데이터에 쉼표가 포함되어 있지 않다는 가정하에 다른 프로그램으로 가져올 수 있는 간단한 CSV와 같은 형식을 출력합니다.

{
        genes[$1] = 1
        for (i = 2; i <= NF; ++i) {
                types[$i] = 1
                counts[$1,$i]++
        }
}

END {
        OFS = ","

        $0 = "name"
        for (t in types)
                $(NF+1) = header[++n] = t
        print

        for (g in genes) {
                $0 = g
                for (i = 1; i <= n; ++i)
                        $(NF+1) = counts[g,header[i]]+0
                print
        }
}

genes배열은 types이름과 유형을 키로 포함하는 연관 배열입니다. 이 counts배열은 입력에서 특정 이름과 유형이 쌍으로 나타나는 횟수를 계산합니다.

END블록은 제목을 생성하고 출력한 다음 모든 유전자 이름을 반복하고 각 유형에 대해 수집된 개수를 출력합니다.

이것을 테스트해 보세요:

$ awk -f script file
name,indel,Benign,Likely_pathogenic,snp,Pathogenic
GeneA,2,1,1,3,3
GeneB,1,2,0,2,1
GeneC,0,1,1,2,0
$ awk -f script file | column -t -s,
name   indel  Benign  Likely_pathogenic  snp  Pathogenic
GeneA  2      1       1                  3    3
GeneB  1      2       0                  2    1
GeneC  0      1       1                  2    0
$ awk -f script file | csvlook
| name  | indel | Benign | Likely_pathogenic | snp | Pathogenic |
| ----- | ----- | ------ | ----------------- | --- | ---------- |
| GeneA |     2 |      1 |              True |   3 |          3 |
| GeneB |     1 |      2 |             False |   2 |          1 |
| GeneC |     0 |      1 |              True |   2 |          0 |

(원치 않으시면csvlook데이터에서 유형을 추론하려면 해당 데이터와 해당 -I옵션을 사용하세요. )

답변2

댓글 상자에서 말했듯이 Ruby가 허용되며 다른 프로그램을 파이핑할 필요가 없는 독립형 솔루션이 있습니다.

프로그램

data = <<~'EOF'
    GeneA Pathogenic snp
    GeneA Pathogenic snp
    GeneA Benign indel
    GeneA Likely_pathogenic snp
    GeneA Pathogenic    indel
    GeneB Benign    snp
    GeneB Pathogenic    snp
    GeneB Benign    indel
    GeneC  Benign   snp
    GeneC  Likely_pathogenic    snp
EOF

hash, header1, header2 = {}, [], []

data.each_line { |x|
    fields = x.split("\s")
    field = hash[fields[0].to_sym] ||= [{}, {}]

    field[0].merge!(fields[1] => 1) { |key, val1, val2| val1 + val2 }
    field[1].merge!(fields[2] => 1) { |key, val1, val2| val1 + val2 }
    header1 << fields[1]
    header2 << fields[2]
}

headers = header1.tap(&:uniq!).concat(header2.tap(&:uniq!))
header = '| ' + headers.join(' | ') + ' | '

puts header, ?- * header.length

hash.each { |k, v|
    v0, v1 = v[0], v[1]

    print "| #{k} |"
    headers.each_with_index { |x, i|
        out = "#{(v0[x] || v1[x]).to_i} |"
        print i == 0 ? out.rjust(5) : out.rjust(x.length + 3)
    }
    puts
}

구현하다:

$ ruby thisFile.rb

산출:

| Pathogenic | Benign | Likely_pathogenic | snp | indel | 
----------------------------------------------------------
| GeneA |  3 |      1 |                 1 |   3 |     2 |
| GeneB |  1 |      2 |                 0 |   2 |     1 |
| GeneC |  0 |      1 |                 1 |   2 |     0 |

하드코딩되어 있기 rjust(5)때문에 소리를 지르실 수도 있습니다 . rjust(x.length + 3)실제로 이것들은 타겟으로 지정되어 ' | '있으며 하드코딩되어 있습니다. 공백을 하나 더 추가하면 숫자가 1씩 늘어납니다. 데이터가 변경되어도 깨지지 않습니다.

data <<~EOF...를 사용하는 대신 를 사용하여 데이터가 포함된 파일을 읽을 수 있습니다. data = (ARGV[0] && File.readable?(ARGV[0])) ? IO.read(ARGV[0]) : ''여기서 데이터는 인수로 전달된 파일 이름에서 읽습니다. 모든 데이터에 대해 작동해야 하지만 정렬은 헤더를 기반으로 수행됩니다. 이 코드를 약간 수정하면 가장 큰 필드를 기준으로 데이터를 정렬할 수 있습니다. 하지만 이제는 이것이 당신의 일이 될 것이라고 생각합니다.

관련 정보