예제 코드를 기반으로 세 번째 열의 다양한 용어를 하나의 행으로 결합합니다.

예제 코드를 기반으로 세 번째 열의 다양한 용어를 하나의 행으로 결합합니다.

세 개의 열이 있는 게놈 데이터가 있습니다. 1열은 표본, 2열은 암 유형, 3열은 메커니즘입니다. 각 샘플에는 세 번째 행에 할당된 하나 이상의 유전자 메커니즘이 있습니다(예: 6 ecDNA). 현재 샘플당 각 메커니즘에 대해 여러 행이 있습니다. 예를 들어 샘플 x에는 "6 ecDNA" 메커니즘에 대한 4개 행과 "5 삭제" 메커니즘에 대한 5개 행이 있으며, 각 행은 해당 샘플에서 발견된 하나의 유전적 이상에 해당합니다. .

각 샘플의 데이터에 있는 모든 종류의 메커니즘을 한 행에 표시할 수 있는 방법이 있는지 궁금합니다.

(예: 암 약어 메커니즘 예)

     x        Bladder     6 ecDNA, 5 deletion

샘플의 메커니즘 유형을 한 줄로 압축하는 방법이 있나요? 편집: 다음은 샘플 "x" 및 "y"가 포함된 OG 데이터 세트의 대표적인 테이블입니다.

샘플, 암 약어, 메커니즘

 x,       Bladder,         6 ecDNA

 x,       Bladder,         6 ecDNA

 x,       Bladder,         5 deletion

 x,       Bladder,         5 deletion

 y,       Osteosarcoma,    4 transposition

 y,       Osteosarcoma,    4 transposition

y,       Osteosarcoma,    5 deletion

y,       Osteosarcoma,    6 ecDNA

....

답변1

#!/usr/bin/perl
use strict;

my %rec;

while(<>) {
  chomp;
  s/^\s+|\s*$//;
  next if m/^$/;

  my ($c1,$c2,$c3) = split /\s{2,}|\t+/;

  $rec{$c1}->{$c2}->{$c3} = 1;
}

# find the largest widths (lengths) of the first two columns, minimum 6 for each
my $l1=6;
my $l2=6;
foreach my $k1 (keys %rec) {
  $l1 = length($k1) if (length($k1) > $l1);
  foreach my $k2 (keys %{ $rec{$k1} }) {
    $l2 = length($k2) if (length($k2) > $l2);
  }
};

# use that to build a format string
my $fmt = "%-${l1}s\t%-${l2}s\t%s\n";

printf $fmt, "Sample", "Cancer", "Mechanisms";

foreach my $k1 (sort keys %rec) {
  foreach my $k2 (sort keys %{ $rec{$k1} }) {
    printf $fmt, $k1, $k2, join(", ",sort keys %{ $rec{$k1}->{$k2} });
  };
}

이 Perl 스크립트는 각 입력 줄을 읽고 선행 또는 후행 공백을 제거하고 빈 줄을 건너뜁니다. 입력 파일에 각 열을 구분하는 하나 이상의 탭만 있는지, 아니면 여러 개의 공백 문자가 있는지 잘 모르겠습니다. 저는 그 중 하나를 처리하기 위해 작성했습니다.

각 레코드를 보유하기 위해 %rec라는 데이터 구조를 구축합니다. 데이터 구조는 처음 두 수준이 처음 두 열(샘플 및 암)의 이름이고 세 번째 수준에 메커니즘이 포함된 다중 수준 해시(연관 배열)입니다.

즉, %rec 데이터 구조는 다음과 같습니다.

%rec = {
  x => { Bladder => { "5 deletion" => 1, "6 ecDNA" => 1 } },
  y => { Osteosarcoma => { "4 transposition" => 1, "5 deletion" => 1, "6 ecDNA" => 1 }, },
}

Perl 데이터 구조에 대한 자세한 내용은 man perldsc또는를 참조하세요. 이러한 데이터 구조를 만들고 사용하는 방법에 대한 간단한 튜토리얼 perldoc perldsc도 참조하세요 . man perlreftut0

전체 입력 파일 읽기가 끝나면 각 레코드에 대한 요약 줄을 인쇄합니다(각 열의 너비를 계산한 후). 출력은 탭으로 구분됩니다.

예를 들어 로 저장 combine.pl하고 실행 가능하게 만듭니다 chmod +x.

$ chmod +x ./combine.pl
$ ./combine.pl input.txt
Sample  Cancer          Mechanisms
x       Bladder         5 deletion, 6 ecDNA
y       Osteosarcoma    4 transposition, 5 deletion, 6 ecDNA

답변2

datamash간단한 도구입니다. 그러나 빈 줄을 제거하고 데이터 입력 형식에 더 많은 주의를 기울여야 합니다.

sed '/^$/d' infile | datamash -W -g 1,2 unique 3,4

열 1과 2를 기준으로 그룹화한 후 열 3과 4를 쉼표로 구분된 목록으로 축소하지만 고유한 값만 표시함을 나타냅니다. -W탭 대신 공백을 필드 구분 기호로 사용함을 나타냅니다. sed빈 줄을 삭제하면 됩니다. 이러한 출력을 생성하는 입력 파일을 사용하십시오.

Sample  Cancer  Abbrev  Mechanism
x   Bladder 5,6 deletion,ecDNA
y   Osteosarcoma    4,5,6   deletion,ecDNA,transposition

Abbrev와 Mechanism이 어떻게 별도로 그룹화되어 있는지 확인하고 서로 독립적으로 정렬된다는 점에 유의하세요(예: 4deletion가 첫 번째이고 입력이 4와 같음 transposition). 이는 unique정렬이 필요한 작업에서 비롯됩니다. 요청한 정확한 출력을 위해 다음이 작동합니다.

awk 'BEGIN {OFS="\t"} $0 != "" {print $1,$2,$3" "$4}' infile |
datamash -g 1,2 unique 3

Sample  Cancer  Abbrev Mechanism
x   Bladder 5 deletion,6 ecDNA
y   Osteosarcoma    4 transposition,5 deletion,6 ecDNA

여기서는 awk필드를 탭으로 구분하는 데 사용되지만, 필드 3과 4를 하나로 병합하려면 필드 3과 4 사이에 공백을 남겨두기만 하면 됩니다. 이렇게 하면 datamash기본적으로 탭 문자를 구분 기호로 전달하므로 전체로 처리됩니다. awk또한 여기에서 빈 줄을 필터링합니다.

답변3

사용밀러, 입력이 CSV인 경우 실행할 수 있습니다.

mlr --c2t -N nest --implode --values --across-records --nested-fs "," -f 3 then clean-whitespace input.csv

가지다

x Bladder      6 ecDNA,6 ecDNA,5 deletion,5 deletion
y Osteosarcoma 4 transposition,4 transposition,5 deletion,6 ecDNA

내가 사용한 입력 파일

x,Bladder,6 ecDNA
x,Bladder,6 ecDNA
x,Bladder,5 deletion
x,Bladder,5 deletion
y,Osteosarcoma,4 transposition
y,Osteosarcoma,4 transposition
y,Osteosarcoma,5 deletion
y,Osteosarcoma,6 ecDNA

고유한 값을 원하는 경우 명령은 다음과 같습니다.

mlr --c2p -N uniq -a then  nest --implode --values --across-records --nested-fs "," -f 3 then clea
n-whitespace input.csv

답변4

사용 awk:

세 번째와 네 번째 필드에 고정 값이 있다고 가정하면, 즉 6세 번째 필드의 ecDNA네 번째 필드에는 항상 고정 값이 있다고 가정하면 다음과 같이 작동합니다.

awk 'BEGIN{FS=",";OFS="\t"; printf "Sample\tCancer\tMechanisms\n"}
NF{len=split(ar[$1 OFS $2], a, " ");   
for(i=1;i<=len;i++) if (a[i] == $4) $4="";
if ($4) ar[$1 OFS $2]=(ar[$1 OFS $2] ? ar[$1 OFS $2]  ", " : "") $3 " " $4}
END{for(j in ar) print j,ar[j]}' input

위 명령에서는 FS=","열이 쉼표로 구분되어 있고 OFS="\t"탭으로 구분된 열을 원하기 때문입니다.

관련 정보