여러 파일을 효율적으로 연결

여러 파일을 효율적으로 연결

여러 파일을 결합하는 방법에 대한 게시물이 있다는 것을 알고 있지만 시간이 많이 걸렸습니다. 첫 번째 열이 환자 ID인 파일이 여러 개 있고 첫 번째 열의 ID 번호를 기준으로 여러 파일을 결합하고 싶습니다.

아래 코드는 여전히 작동하지만 시간이 많이 걸립니다. 그렇다면 이 프로세스를 보다 효율적으로 수행하는 방법을 아는 사람이 있습니까?

for PHENO in A B C D E F G H I J K L M
do
    join -a1 -a2 -e 1 -o auto chr2_${PHENO} chr3_${PHENO} >${PHENO}
done

for PHENO in A B C D E F G H I J K L M
do
    for file in chr5_${PHENO} chr11_${PHENO} chr14_${PHENO} chr20_${PHENO} \
    chr21_${PHENO} chr22_${PHENO} chr6_${PHENO} chr9_${PHENO} chr13_${PHENO} \
    chr18-1_${PHENO} chr18-2_${PHENO} chr1-1_${PHENO} chr1-2_${PHENO} \
    chr1-3_${PHENO} chr8-1_${PHENO} chr8-2_${PHENO} chr17-1_${PHENO} \
    chr17-2_${PHENO} chr19-1_${PHENO} chr19-2_${PHENO} chr19-3_${PHENO} \
    chr19-4_${PHENO} chr4-1_${PHENO} chr4-2_${PHENO} chr4-3_${PHENO} \
    chr4-4_${PHENO} chr7-1_${PHENO} chr7-2_${PHENO} chr7-3_${PHENO} \
    chr10-1_${PHENO} chr10-2_${PHENO} chr10-3_${PHENO} chr10-4_${PHENO} \
    chr12-1_${PHENO} chr12-2_${PHENO} chr12-3_${PHENO} chr12-4_${PHENO} \
    chr15-1_${PHENO} chr15-2_${PHENO} chr15-3_${PHENO} chr16-1_${PHENO} \
    chr16-2_${PHENO} chr16-3_${PHENO}; do
        join -a1 -a2 -e 1 -o auto ${PHENO} "$file" >${PHENO}.1
        mv ${PHENO}.1 ${PHENO}
    done
done

모든 파일은 아래에 있습니다. 150,001명의 환자는 아픈지 여부를 0 또는 1로 표시합니다. 예를 들어 chr2_${PHENO}

ID Disease
1 0
2 1
3 0 
4 1
5 1
....

150000 0 
150001 1

예를 들어 chr3_${PHENO}

ID Disease
1 1
2 1
3 1 
4 0
5 0
....

150000 0 
150001 0

미리 감사드립니다!

답변1

좋아요 이것은답변 자체는 아님, 하지만 상황을 명확히 하기 위한 게시물일 수도 있습니다.

질문에 필요한 내용을 포함하세요.

(죄송합니다. 일반적인 작업 방식은 아니지만...)


이것이 귀하의 파일과 원하는 결과와 유사합니까?

다음은 두 가지 예제 스크립트입니다. 먼저 더미 파일을 생성합니다.

  • chr1_A도착하다문자6_A
  • 문자 1_B도착하다chr6_B
  • chr1_C도착하다chr6_C

용도별로 정렬LC_ALL=C sort -k 1b,1

#! /bin/bash
for p in A B C; do
    for i in $(seq 1 6); do
        f="chr${i}_$p"
        printf 'ID %s\n' "$i.$p" >"$f"
        paste <(shuf -n 24 -i 1-222) <(shuf -n 24 -i 0-1 -r) | \
            LC_ALL=C sort -k 1b,1 >>"$f"
    done
done

예를 들어 샘플 그룹이 주어지면 다음과 같습니다.paste chr* | column -t

ID   1.A  ID   1.B  ID   1.C  ID   2.A  ID   2.B  ID   2.C  ...
116  1    107  1    101  0    110  1    105  1    111  0    ...
126  1    11   1    105  0    111  1    106  1    117  1    ...
131  1    111  0    106  0    121  0    113  0    121  0    ...
141  0    133  0    110  0    124  0    147  0    145  0    ...
167  1    135  1    113  1    135  0    154  0    146  1    ...
...

이것이 맞는지 확실하지 않으면 결정하십시오.


두 번째 스크립트는 수정된 버전입니다(예: 실제 데이터와 구별하기 위해 대시를 사용하여 누락을 나타냄).

#! /bin/bash

for PHENO in A B C; do
    join -a1 -a2 -e - -o auto chr1_${PHENO} chr2_${PHENO} >${PHENO}
done

for PHENO in A B C; do
    for n in 3 4 5 6; do
        file="chr${n}_$PHENO"
        join -a1 -a2 -e - -o auto ${PHENO} "$file" >${PHENO}.1
        mv ${PHENO}.1 ${PHENO}
    done
done

A, B, C 세 개의 파일을 생성합니다.

$ paste A B C | column -t
ID   1.A  2.A  3.A  4.A  5.A  6.A  ID   1.B  2.B  3.B  4.B  5.B  6.B  ID   1.C  2.C  3.C  4.C  5.C  6.C
10   -    -    1    1    -    -    101  -    -    1    -    -    1    101  0    -    0    -    -    1
100  -    -    -    0    -    -    102  -    -    -    -    -    0    103  -    -    -    -    -    0
102  -    -    1    -    0    -    105  -    1    0    -    0    -    105  0    -    -    -    -    -
108  -    -    0    -    -    -    106  -    1    -    -    -    1    106  0    -    -    -    1    -
109  -    -    -    -    -    1    107  1    -    -    -    -    -    107  -    -    -    -    -    0
110  -    1    -    -    -    -    109  -    -    -    -    -    0    108  -    -    -    -    -    0
111  -    1    -    -    -    -    11   1    -    -    -    -    -    109  -    -    -    1    0    -
116  1    -    -    -    -    -    111  0    -    -    -    -    -    110  0    -    -    -    -    -
117  -    -    -    -    1    -    113  -    0    -    -    -    -    111  -    0    -    -    -    -

...

# or
# paste <(sort -n A) <(sort -n B) <(sort -n C) | column -t

답변2

나는 다른 접근 방식을 제안하고 싶습니다.

  1. chr1_A모든 파일에 15,000개의 항목이 모두 포함되어 있고 정렬되어 있는지 확인하세요 ! 여기에는 누락된 부분에 "1"을 채우는 것도 포함됩니다.
  2. 이러한 각 파일을 "질병" 열로만 줄이세요.
  3. 각 PHENO에 대한 "ID" 열을 포함하는 파일을 만듭니다.
  4. 이제 축소된 파일을 ID 열 파일과 연결하는 대신 붙여넣습니다. (정렬되어 있으며 행은 지점 1부터 일치해야 합니다)
  5. 병렬화를 위한 스크립트를 만듭니다.

어떻게:

  1. +2. Pass awk-script로 이름을 지정합니다.fillrows.awk

    NR>1 {disease[$1]=$2}
    END {print FILENAME
         for (i=1;i<=15000;i++) {
           if (disease[i]!="")
              {print disease[i] > FILENAME"_red"}
           else {print "1" > FILENAME"_red"}
         }
    }
    

chr1_A그러면 다음과 유사한 파일이 생성됩니다 .

 ID Disease
 2  0
 5  1

to chr1_A_red(최대 6줄 표시)

 chr1_A
 1
 0
 1
 1
 1
 1

다음과 같이 실행될 때:awk -f fillrows.awk chr1_A

  1. ID 열은 항상 동일합니다.

    { echo ID ; seq 1 15000 ;} > ID_col
    
  2. 함께 붙여넣기 - RAM에 따라 제한될 수 있습니다.

    for PHENO in {A..M} ; do
      paste ID_col chr*_$PHENO > $PHENO
    done
    
  3. 일부 병렬화GNU 병렬

     #!/bin/bash
     ##get chrX-Y list without PHENO
     find -name 'chr*' | sed 's/_.$//' | sort -u > chrlist
     parallel awk -f rowfill ::: chr*{A..M}
     { echo ID ; seq 1 15000 ;} > ID_col
     parallel paste ID_col '{1}_{2}_red' '>' '{2}' :::: chrlist ::: {A..M}
    

답변3

나는 여러 개의 파일을 연결하는 재귀 함수를 생각해 냈습니다.

join_all() {
    local -a join_opts
    local arg
    while :; do
        arg=$1
        shift
        [[ $arg == '--' ]] && break
        join_opts+=("$arg")
    done

    if (($# == 1)); then
        cat "$1"
    else
        join "${join_opts[@]}" "$1" "$2" | join_all "${join_opts[@]}" -- '-' "${@:3}"
    fi
}


for PHENO in A B C D E F G H I J K L M
do
    files=()
    # use brace expansion to generate the list of files
    files+=( chr{2,3,5,11,14,20,21,22,6,9,13}_${PHENO} )
    files+=( chr{18,8,17}-{1,2}_${PHENO} )
    files+=( chr{1,7,15,16}-{1,2,3}_${PHENO} )
    files+=( chr{19,4,10,12}-{1,2,3,4}_${PHENO} )

    join_all -a1 -a2 -e 1 -o auto -- "${files[@]}" > ${PHENO}
done

관련 정보