100個のファイルがあり、各ファイルには57,816行があります。共通列に基づいてマージして、これらのファイルに対して外部結合を実行したいと思います。
Rでプログラムしていますが、非常に遅いです。
fileList <- list.files(, pattern=".txt")
pm_list=lapply(fileList, read.table)
merged_pm=merge_all(pm_list, by = "gene_short_name")
Bashでこれを行う簡単な方法はありますか?使用できるもう1つの方法はSQLですが、最初に100個のテーブルを作成してから結合する前にロードする必要がありますが、それほど効率的ではありません。
各ファイルの行数は同じです。そのため、共通列に基づいてマージしたいのですが、共通列の定数が他のファイルにわずかに上下に存在しないため、Rでcbindを使用することはできません。ファイルの各場所に同じ場所にあります。以下には2つのサンプルファイルがあります。 「gene_short_name」に基づいて参加したいと思います。
gene_short_name FPKM56
MT-TF 0.90
MT-TV 0
MT-RNR1 310.015
MT-TL1 0
MT-TM 0
ファイル2は次のようになります。
gene_short_name FPKM53
MT-TF 0
MT-TV 0.344
MT-TM 0.10
MT-TL1 0
MT-RNR1 0
MT-ND2 158.332
答え1
次のスクリプトは、パラメータとして渡されたすべてのタブで区切られたファイルの列1(フィールド)に対して外部結合を実行する必要があります。それを使う参加するソートされたファイルに対して一度に2つのファイルを外部結合するコマンドです。
ヘッダー行を含むファイル内のすべての行を連結します。ヘッダーを除外するには、これら2つのsort
コマンドをヘッダーを省略するソートファイルを生成するコマンドに変更します。
#!/bin/sh
if test $# -lt 2
then
echo usage: gjoin file1 file2 ...
exit 1
fi
sort -t $'\t' -k 1 "$1" > result
shift
for f in "$@"
do
sort -t $'\t' -k 1 "$f" > temp
join -1 1 -2 1 -t $'\t' result temp > newresult
mv newresult result
done
cat result
rm result temp
古いシェルを使用している場合、$'\t'
タブは置き換えられないため、を使用する必要があり、引用符の間に 'TAB'リテラルタブを配置する必要があります。
/bin/sh
代わりに、次のような最新のシェル(bashやkshなど)が利用可能な場合は最適化できます。
sort -t $'\t' -k 1 "$f" > temp
join -1 1 -2 1 -t $'\t' result temp > newresult
に取り替えることができる
join -1 1 -2 1 -t $'\t' result <(sort -t $'\t' -k 1 "$f") > newresult
答え2
あなたの投稿によると、最初の列のキーは常に同じであるため(順番のみ)、より速く実行できるsort
と思います。ファイルの1つ(最初の2行を除く)を並べ替え、残りのファイル(最初の2行を除く)を並べ替え、各ファイルから2番目の列のみを抽出して結果を貼り付けることができます。例: :cut
paste
1.txt
g_s_n FPKM56
MT-ND2 21.06
MT-TF 0.90
MT-TV 1
MT-RNR1 310.015
MT-TL1 1
MT-TM 1
2.txt
:
g_s_n FPKM53
MT-TF 0
MT-TV 0.344
MT-TM 0.10
MT-TL1 0
MT-RNR1 0
MT-ND2 158.332
3.txt
:
g_s_n FPKM58
MT-RNR1 0.82
MT-TM 7
MT-TF 1.20
MT-TV 4
MT-ND2 4.05
MT-TL1 2
ランニング:
paste <({ head -n 2; sort; } <1.txt) <({ head -n 2; sort; } <2.txt | cut -f2) \
<({ head -n 2; sort; } <3.txt | cut -f2)
生産する:
g_s_n FPKM56 FPKM53 FPKM58
MT-ND2 21.06 158.332 4.05
MT-RNR1 310.015 0 0.82
MT-TF 0.90 0 1.20
MT-TL1 1 0 2
MT-TM 1 0.10 7
MT-TV 1 0.344 4
仕組み:{ head -n 2; sort; } <1.txt
最初のファイル(最初の2行を除く)をソートして、最初の列(共通)がソートされるようにします。
g_s_n FPKM56
MT-ND2 21.06
MT-RNR1 310.015
MT-TF 0.90
MT-TL1 1
MT-TM 1
MT-TV 1
他のファイルと同じ:{ head -n 2; sort; } <other_files.txt | cut -f2
今回は2番目の列のみを抽出します(その後、sort
最初の列はすべてのファイルに対して同じです)。
FPKM53
158.332
0
0
0
0.10
0.344
そして:
FPKM58
4.05
0.82
1.20
2
7
4
これらはすべて結合されていますpaste
。
もちろん、シェルがプロセス置換をサポートしている場合、上記の方法は限られた数のファイルに適しています。それ以外の場合は、スクリプトを作成し、一時ファイルを使用して(Markの回答で行ったように)、システムの制限に従ってファイルを10、20などのグループに貼り付ける必要があります。