2개의 파일이 있습니다. 파일 1의 열 1은 파일 2의 열 2로 바뀌어야 하며, 파일 1의 열 2,3,4-5 또는 5-4(교차 일치)는 열 1,4,5와 일치합니다. -6 또는 파일 2의 6-5.
파일 1
SNP Chr Pos EA NEA EAF Beta SE Pvalue Neff
1:79137 1 79137 A T 0.25 -0.026 0.0073 4.0e-04 231420
1:79033 1 79033 A G 0.0047 -0.038 0.056 4.9e-01 225429
1:118630 1 118630 C T 0.99 -0.033 0.055 5.5e-01 226311
1:533179 1 533179 A G 1 -0.098 0.19 6.1e-01 185906
파일 2
1 1:79033_A_G 0 79033 A G
1 1:79137_A_T 0 79137 T A
1 1:118630_C_T 0 118630 T C
1 1:533179_A_G 0 533179 G A
다음과 같은 출력이 필요합니다.
SNP Chr Pos EA NEA EAF Beta SE Pvalue Neff
1:79137_A_T 1 79137 A T 0.25 -0.026 0.0073 4.0e-04 231420
1:79033_A_G 1 79033 A G 0.0047 -0.038 0.056 4.9e-01 225429
1:118630_C_T 1 118630 C T 0.99 -0.033 0.055 5.5e-01 226311
1:533179_A_G 1 533179 A G 1 -0.098 0.19 6.1e-01 185906
파일에 정확한 줄 수가 없으며 파일이 탭으로 구분되지 않습니다. 아래 코드를 시도했지만 작동하지 않습니다. 코드를 수정해 주실 수 있나요?
awk 'NR==FNR{chr[$1]=$1;snp[$2]=$2;pos[$4]=$4;a1[$5]=$5;a2[$6]=$6;next} ($1 in chr)&&($4 in pos)&& ((($5 in a1) && ($6 in a2)) || (($6 in a1) && ($5 in a2))) {$2==snp[$2]}' file 2 file1
편집 1:
다음 Perl 코드는 일부 오류를 일으키고 약 20,000개의 중복 행을 생성합니다.
파일 1
SNP Chr Pos EA NEA EAF Beta SE Pvalue Neff
7:10100610 7 10100610 A G 0.0002 0.13 0.58 8.2e-01 120658
7:10100610 7 10100610 C G 0.0013 0.1 0.13 4.4e-01 139170
10:1006107 10 1006107 C G 1 -0.11 0.42 7.9e-01 152016
파일 2
7 7:10100610_G_A 0 10100610 A G
7 7:10100610_G_C 0 10100610 C G
10 10:1006107_C_G 0 1006107 G C
다음 줄의 예상 출력은 다음과 같습니다.
7:10100610_G_A 7 10100610 A G 0.0002 0.13 0.58 8.2e-01 120658
7:10100610_G_C 7 10100610 C G 0.0013 0.1 0.13 4.4e-01 139170
10:1006107_C_G 10 1006107 C G 1 -0.11 0.42 7.9e-01 152016
그러나 Perl 코드는 출력을 제공합니다.
7:10100610_G_A 7 10100610 A G 0.0002 0.13 0.58 8.2e-01 120658
10:1006107_C_G 7 10100610 C G 0.0013 0.1 0.13 4.4e-01 139170
10:1006107_C_G 10 1006107 C G 1 -0.11 0.42 7.9e-01 152016
답변1
이 join
명령은 여러 파일에서 일치하는 줄을 연결하는 작업을 수행합니다. 그러나 입력 파일에 대한 몇 가지 요구 사항이 있으므로 프로세스 중에 몇 가지 임시 파일과 몇 가지 추가 필드를 만들어야 합니다.
awk '{printf $2" "$3" "$4" "$5"%"$1"%"; $1="";print $0 "%" NR }' < file1 | sort > 1.tmp
awk '{print $1" "$4" "$5" "$6"%"$2} $5 != $6 {print $1" "$4" "$6" "$5"%"$2}' < file2 | sort > 2.tmp
join -a 1 -t % -o 1.4 2.2 1.2 1.3 1.tmp 2.tmp | sort -t % -n | awk -F % '!$2{$2=$3}{print $2" "$4}'
단계별로
첫 번째 파일을 전처리합니다.
awk '{printf $2" "$3" "$4" "$5"%"$1"%"; $1="";print $0 "%" NR }''
출력 예:
1 118630 C T%1:118630% 1 118630 C T 0.99 -0.033 0.055 5.5e-01 226311%4
이 4개 필드는 %
다음과 같이 구분됩니다.
- 일치해야 하는 "키"(입력 필드 2-5)
- 원래 첫 번째 열(일치하는 항목이 없는 경우 필수)
- 원래 줄의 나머지 부분
- 원래 줄 번호(나중에 파일 순서를 복원할 수 있도록
sort
)
이 출력은 입력을 정렬해야 하므로 sort
임시 파일로 파이프됩니다 .join
두 번째 파일의 경우:
awk '{print $1" "$4" "$5" "$6"%"$2} $5 != $6 {print $1" "$4" "$6" "$5"%"$2}'
출력 예:
1 118630 C T%1:118630_C_T
1 118630 T C%1:118630_C_T
필드 5와 6이 일치하도록 지정하면 두 번째 줄이 인쇄되고 서로 교체됩니다(동일하지 않은 경우). 여기서 -로 구분된 필드 %
는 다음과 같습니다.
- "키"와 일치해야 함
- 2열
이번에도 출력이 sort
다른 임시 파일로 파이프됩니다.
그런 다음 주요 "참여" 단계가 옵니다.
join -a 1 -t % -o 1.4 2.2 1.2 1.3 1.tmp 2.tmp
두 번째 그룹에 일치하는 항목이 없을 때 -a 1
첫 번째 그룹의 행을 유지하도록 지시합니다 . 구분 기호를 (공백 대신)로 설정합니다. 이 매개변수는 다음 4개의 출력 필드를 생성합니다.join
-t %
%
-o
- 파일 1, 열 4: 줄 번호
- 파일 2, 열 2: 대체 위치
file2
(일치하는 항목이 없으면 비어 있음) - 파일 1, 열 2: 원본 열 1
file1
- 파일 1, 열 3: 행의 나머지 부분은
file1
예제 출력 라인:
4%1:118630_C_T%1:118630% 1 118630 C T 0.99 -0.033 0.055 5.5e-01 226311
그런 다음 sort
원래 파일 순서를 복원할 수 있습니다(숫자 정렬, 필드 구분 기호 %
).
sort -t % -n
마지막으로 awk
"교체" 필드가 비어 있는지 확인하고(일치하는 항목이 없기 때문에) 비어 있는 경우 원래 열1을 사용합니다. 또한 줄 번호와 모든 을 버립니다 %
.
awk -F % '!$2{$2=$3}{print $2" "$4}'
최종 출력 라인:
1:118630_C_T 1 118630 C T 0.99 -0.033 0.055 5.5e-01 226311
답변2
저는 Perl에서 이것을 할 것입니다. 왜냐면 Perl에는 and를 같은 것으로 sort
쉽게 처리할 수 있는 기능이 있기 때문입니다. 예를 들어(모든 예제 파일의 출력을 결합하여 표시):A T
T A
$ perl -lane 'if(!$k){$name{join("","chr".$F[0],$F[3],sort($F[4],$F[5]))}=$F[1]; }else{$var=join("", "chr".$F[1],$F[2],sort($F[3],$F[4])); $F[0]=$name{$var} if $name{$var};print join "\t", @F; } $k++ if eof' file2 file1
SNP Chr Pos EA NEA EAF Beta SE Pvalue Neff
7:10100610_G_A 7 10100610 A G 0.0002 0.13 0.58 8.2e-01 120658
7:10100610_G_C 7 10100610 C G 0.0013 0.1 0.13 4.4e-01 139170
10:1006107_C_G 10 1006107 C G 1 -0.11 0.42 7.9e-01 152016
1:79137_A_T 1 79137 A T 0.25 -0.026 0.0073 4.0e-04 231420
1:79033_A_G 1 79033 A G 0.0047 -0.038 0.056 4.9e-01 225429
1:118630_C_T 1 118630 C T 0.99 -0.033 0.055 5.5e-01 226311
1:533179_A_G 1 533179 A G 1 -0.098 0.19 6.1e-01 185906
또는 약간 더 명확합니다.
$ perl -lane 'if(!$k){
$name{join("","chr".$F[0],$F[3],sort($F[4],$F[5]))}=$F[1];
}
else{
$var=join("", "chr".$F[1],$F[2],sort($F[3],$F[4]));
$F[0]=$name{$var} if $name{$var};
print join "\t", @F;
}
$k++ if eof' file2 file1
SNP Chr Pos EA NEA EAF Beta SE Pvalue Neff
7:10100610_G_A 7 10100610 A G 0.0002 0.13 0.58 8.2e-01 120658
7:10100610_G_C 7 10100610 C G 0.0013 0.1 0.13 4.4e-01 139170
10:1006107_C_G 10 1006107 C G 1 -0.11 0.42 7.9e-01 152016
1:79137_A_T 1 79137 A T 0.25 -0.026 0.0073 4.0e-04 231420
1:79033_A_G 1 79033 A G 0.0047 -0.038 0.056 4.9e-01 225429
설명하다
perl -lane
: 이는-a
Perl을 awk처럼 동작하게 하며 자동으로 입력을 공백의 배열로 분할합니다@F
. Perl 배열은 첫 번째 필드 로 시작0
하므로 두 번째 필드가 됩니다. 필드 N은 입니다 . Perl이 인수를 텍스트 파일로 읽고 주어진 스크립트를 각 행 에 적용하도록 합니다 . 각 입력 줄에서 후행 개행 문자를 제거하고 각 호출에 개행 문자를 추가하기 만 하면 됩니다 .$F[0]
$F[1]
$F[N-1]
-n
-e
-l
print
$k++ if eof
$k
: 파일의 끝(eof
)에 도달하면 변수가 1 증가합니다. 그런 다음if(!$k)
($k가 정의되지 않은 경우)NR==FNR
awk에서 동등한 것으로 사용할 수 있습니다 .if(!$k){$name{join("","chr".$F[0],$F[3],sort($F[4],$F[5]))}=$F [1];}
: if this is the first file,
file2, join fields 1, 4, and the sorted fields 5 and 6, into a string and use that string as the key in the hash (associative array)
name. Then, save the variant's name from file2 as the value associated with that key. The sorting lets us treat
ATand
TAas equivalent. I use
"chr".$F[0]to deal with cases like
1 123and
11 23`, 여기서 염색체와 위치를 연결하면 염색체가 실제로 다르더라도 동일한 번호가 제공됩니다.else{
: 지금 두 번째 파일을 읽고 있다면file1
.$var=join("", $F[1],$F[2],sort($F[3],$F[4]));
: 빌드 키. 이번에는 필드 2, 3을 사용하고 4와 5를 정렬합니다.$F[0]=$name{$var} if $name{$var};
name
: 키에 값이 있으면 첫 번째 필드를 해시에 저장된 값으로 설정합니다. 헤더 나 존재하지만 존재하지 않는 다른 변형을if
변경하지 않도록 해야 합니다 .file1
file2
print join "\t", @F;
:위에서 변경한 내용을 포함하여 필드를 인쇄합니다.