複数のファイルを結合する方法に関する投稿があることを知っていますが、時間がかかりました。最初の列が患者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
わかりました答え自体ではないしかし、状況を明確にするための投稿かもしれません。
質問に必要なものを含めてください。
(申し訳ありませんが、一般的な作業方法ではありませんが…)
これはあなたのファイルと望む結果に似ていますか?
以下は2つのサンプルスクリプトです。まずダミーファイルを生成します。
- 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 ...
...
これが正しいかどうかわからない場合は決定してください。
2番目のスクリプトは変更されたバージョンです(たとえば、実際のデータと区別するためにダッシュを使用して欠落していることを示します)。
#! /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 3 つのファイルを生成します。
$ 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
私は別のアプローチを提案したいと思います。
chr1_A
すべてのファイルに15,000個のアイテムがすべて含まれており、並べ替えられていることを確認してください。これには、欠けている部分に「1」を埋めることも含まれます。- これらの各ファイルを「病気」列にのみ減らしてください。
- 各PHENOの「ID」列を含むファイルを作成します。
- これで、縮小されたファイルをID列ファイルに関連付ける代わりに貼り付けます。 (ソートされており、行はポイント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
ID列は常に同じです。
{ echo ID ; seq 1 15000 ;} > ID_col
貼り付け - RAMによって制限されることがあります。
for PHENO in {A..M} ; do paste ID_col chr*_$PHENO > $PHENO done
いくつかの並列化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