2개 행마다 합을 계산하고 그 합이 특정 값보다 작으면 다른 값으로 대체합니다.

2개 행마다 합을 계산하고 그 합이 특정 값보다 작으면 다른 값으로 대체합니다.

200만 개의 행과 12개의 열이 있는 유전자형 행렬(테이블스페이스 포함)이 있습니다. 열은 개인이고 행은 SNP입니다. 한 사람당 각 SNP에 대해 2개의 행이 있습니다. 하나는 참조 대립 유전자의 수이고 다른 하나는 대체 대립 유전자의 수입니다(2개 행마다 SNP에 해당합니다. 즉, 행 1과 2는 SNP 1, 행 3과 4에 해당함을 의미합니다) SNP 1) SNP2에 해당하고, 5행과 6행은 SNP 3)에 해당합니다.

다음은 예입니다(2개의 SNP와 8명의 개인).

head genotype
2   3   1   0   0   3   5   3       
18  15  19  18  16  15  13  17      
2   1   0   0   0   1   1   1           
18  19  18  16  20  17  17  23  

각 SNP에 대해 참조 대립 유전자와 대체 대립 유전자의 합이 20보다 작으면 두 대립 유전자를 모두 0으로 바꾸고, 20보다 크거나 같으면 유지하고 싶습니다. 이것이 내가 원하는 출력이다

head (desired_output)
    2   0   1   0   0   0   0   3       
    18  0   19  0   0   0   0   17      
    2   1   0   0   0   0   0   1           
    18  19  0   0   20  0   0   23  

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

답변1

아이디어는 두 개의 배열에 연속된 행을 저장한 다음 해당 인덱스를 기준으로 배열 요소를 비교하는 것입니다.

"twenty.awk"와 같은 파일에 저장하세요.

#/usr/bin/env awk

# ref https://www.gnu.org/software/gawk/manual/html_node/Join-Function.html
function join(array, start, end, sep,    result, i)
{
    if (sep == "")
        sep = " "
    else if (sep == SUBSEP) # magic value
        sep = ""
    result = array[start]
    for (i = start + 1; i <= end; i++)
        result = result sep array[i]
    return result
}

{
    split($0, a)
    getline

    for (i=1; i<=NF; i++)
        if (a[i] + $i < 20)
            a[i] = $i = 0

    print join(a, 1, NF)
    print
}

그런 다음 실행

awk -f twenty.awk data.file | column -t > data.file.twenty

관련 정보