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에서 이 작업을 수행하는 빠른 방법이 있습니까? 사용할 수 있는 또 다른 방법은 SQL이지만 먼저 100개의 테이블을 만든 다음 조인하기 전에 로드해야 하는데 이는 그리 효율적이지 않습니다.
각 파일의 행 수가 동일합니다. 그래서 공통 열을 기반으로 병합하고 싶지만 공통 열의 상수가 다른 파일에서 약간 위아래로 존재하지 않기 때문에 R에서 cbind를 사용할 수 없습니다. 파일의 각 위치에 같은 위치에 있습니다. 아래에는 두 가지 예제 파일이 있습니다. "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개의 파일씩 외부 조인을 수행하는 명령입니다.
헤더 줄을 포함하여 파일의 모든 줄을 연결합니다. 헤더를 제외하려면 이 두 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
있다고 생각합니다 . 파일 중 하나(처음 두 행 제외)를 정렬한 다음 나머지 파일(역시 처음 두 행 제외)을 정렬하고 각 파일에서 두 번째 열만 추출하여 결과를 붙여넣을 수 있습니다. 예: :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
첫 번째 파일(처음 두 행 제외)을 정렬하여 이제 첫 번째 열(공통)이 정렬되도록 합니다.
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
이번에는 두 번째 열만 추출합니다(그 후 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 등의 그룹으로 붙여넣어야 합니다.