탭으로 구분된 일부 파일 병합

탭으로 구분된 일부 파일 병합

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있다고 생각합니다 . 파일 중 하나(처음 두 행 제외)를 정렬한 다음 나머지 파일(역시 처음 두 행 제외)을 정렬하고 각 파일에서 두 번째 열만 추출하여 결과를 붙여넣을 수 있습니다. 예: :cutpaste
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 등의 그룹으로 붙여넣어야 합니다.

관련 정보