2つのタブで区切られたテキストファイルがあります。より大きなデフォルトファイルであるファイル1には複数の列がありますが、ファイル2は、制限された行の最初の2つの列のみがファイル2と共有する小さなファイルです。
File 3を出力として持ち、2つのファイルの最初の列の間に一致する行を除いて、File 1の他のすべての列を印刷したいと思います。
試してみましたがgrep -vf
うまくいかないようです。また、両方の列の一致が必要です。
ファイル1:
BP CHR SNP REF ALT A1 OBS_CT OR LOG(OR)_SE Z_STAT P
1650048 1 rs112618790 C T T 12387 1.00246 0.0877604 0.0279678 0.977688
1856473 1 rs6684487 G A A 12387 1.02222 0.0836593 0.262689 0.79279
ファイル2:
BP CHR
1650048 1
1650483 1
出力(ファイル3):
BP CHR SNP REF ALT A1 OBS_CT OR LOG(OR)_SE Z_STAT P
1856473 1 rs6684487 G A A 12387 1.02222 0.0836593 0.262689 0.79279
答え1
ファイルが最初のフィールドに基づいてソートされていると仮定すると、次のコマンドを使用して、最初のフィールドが2番目のファイルに表示されない最初のファイルのすべてのレコードを抽出できます。
$ join -v 1 file1 file2
1856473 1 rs6684487 G A A 12387 1.02222 0.0836593 0.262689 0.79279
タブ区切り記号とタイトルを保持するには:
$ head -n 1 file1; join -t $'\t' -v 1 file1 file2
BP CHR SNP REF ALT A1 OBS_CT OR LOG(OR)_SE Z_STAT P
1856473 1 rs6684487 G A A 12387 1.02222 0.0836593 0.262689 0.79279
一致のために最初と2番目のフィールドの両方を使用するには、両方のファイルのこれらのフィールドに基づいて結合された新しい最初のフィールドを作成し、そのフィールドに結合してから一時結合フィールドを削除します。これは基本的に次のようなものを実装します。装飾 - 並べ替え - 装飾キャンセルしかし、ソートにはリレーショナルJOIN操作を使用します。
次のコードでは、シェルを使用できると仮定しています<(...)
。
$ head -n 1 file1; join -t $'\t' -v 1 <( awk -F '\t' 'BEGIN { OFS=FS } { print $1 "_" $2, $0 }' file1 ) <( awk -F '\t' 'BEGIN { OFS=FS } { print $1 "_" $2, $0 }' file2 ) | cut -f 2-
BP CHR SNP REF ALT A1 OBS_CT OR LOG(OR)_SE Z_STAT P
1856473 1 rs6684487 G A A 12387 1.02222 0.0836593 0.262689 0.79279
または、ヘルパーシェル機能を使用してコマンドを読みやすくします。
$ decorate () { awk -F '\t' 'BEGIN { OFS=FS } { print $1 "_" $2, $0 }' "$1"; }
$ head -n 1 file1; join -t $'\t' -v 1 <( decorate file1 ) <( decorate file2 ) | cut -f 2-
BP CHR SNP REF ALT A1 OBS_CT OR LOG(OR)_SE Z_STAT P
1856473 1 rs6684487 G A A 12387 1.02222 0.0836593 0.262689 0.79279
答え2
1つのオプションは、次のものを使用することですawk
。
awk '
# set the input Field Seperator to a Tab
BEGIN { FS="\t" }
# store column#1,column#2 of file2 into associated array bp_file2
NR==FNR{ bp_file2[$1, $2]; next }
# do not print lines of file1 if column#1 was in the array
# with FNR==1 we are printing the first header line too
!(($1, $2) in bp_file2) || FNR==1
' file2 file1
答え3
Pythonソリューション。おそらく他のものよりも長いですが、読みやすくなります(私はどうですか?)。
file1 = '1'
file2 = '2'
separator = '\t'
list2=[]
# first building up a list of IDs from file2:
with open(file2) as f:
for line in f:
if line[0].isdigit(): # only process lines which start with number
list2.append(line.split(separator)[0])
# then go through file1 and check IDs from the previously built list
with open(file1) as f:
print(f.readline(), end='') # printing out header
for line in f:
if not line.split(separator)[0] in list2:
# print out line which IDs are not in list2 (not in file2)
print(line, end='')
次のように実行してください。
python3 file.py > 3
答え4
awk 'BEGIN{print "BP CHR SNP REF ALT A1 OBS_CT OR LOG(OR)_SE Z_STAT P"}NR==FNR{a[$1];next}!($1 in a){print $0}' file2 file1
出力
BP CHR SNP REF ALT A1 OBS_CT OR LOG(OR)_SE Z_STAT P
1856473 1 rs6684487 G A A 12387 1.02222 0.0836593 0.262689 0.79279
Python
#!/usr/bin/python
import re
f1=open('/home/praveen/file1','r')
f2=open('/home/praveen/file2','r')
f3=open('/home/praveen/file3','w')
f1.readline()
f2.readline()
for i in f2:
i_split=i.split(' ')
# print i.split(' ')
for j in f1:
j_split=j.split(' ')
if (i_split[0] != j_split[0]):
str_append="BP CHR SNP REF ALT A1 OBS_CT OR LOG(OR)_SE Z_STAT P"
appnddata="{0}\n{1}\n".format(str_append,j.strip())
f3.write(appnddata)
出力
BP CHR SNP REF ALT A1 OBS_CT OR LOG(OR)_SE Z_STAT P
1856473 1 rs6684487 G A A 12387 1.02222 0.0836593 0.262689 0.79279