열의 필드를 분리하고(이름이 지정된 자체 열에 배치) 각 항목에서 중복 단어를 제거하려면 어떻게 해야 합니까?

열의 필드를 분리하고(이름이 지정된 자체 열에 배치) 각 항목에서 중복 단어를 제거하려면 어떻게 해야 합니까?

다음과 같이 9개의 변수를 포함하는 tsv 파일이 있습니다.

> seqnames  start   endwidth    strand  metadata    X.10logMacsq    annotation  distanceToTSS

메타데이터 열에는 분석하려는 정보가 포함되어 있지만 먼저 항목을 분할하여 헤더가 있는 자체 열에 넣어야 합니다. 메타데이터는 다음과 같습니다(첫 번째 행).

ID=SRX067411;Name=H3K27ac%20(@%20HMEC);Title=GSM733660:%20Bernstein%20HMEC%20H3K27ac;Cell%20group=Breast;<br>source_name=HMEC;biomaterial_provider=Lonza;lab=Broad;lab%20description=Bernstein%20-%20Broad%20Institute;datatype=ChipSeq;datatype%20description=Chromatin%20IP%20Sequencing;cell%20organism=human;cell%20description=mammary%20epithelial%20cells;cell%20karyotype=normal;cell%20lineage=ectoderm;cell%20sex=U;antibody%20antibodydescription=rabbit%20polyclonal.%20Antibody%20Target:%20H3K27ac; 

이 열에는(행당) 총 27개의 항목이 있지만(여기에 모두 표시되지는 않음) 먼저 해당 항목을 모두 해당 열에 기록한 다음 필요하지 않은 항목을 삭제해야 한다고 생각했습니다. 설명적인 열 제목이 있으면 이름을 제거할 수도 있습니다(예: ID=SRX 그냥 SRX 등).

샘플 파일 입력(첫 번째 줄)

seqnames    start   end width   strand  metadata    X.10logMacsq    annotation  geneChr geneStart   geneEnd geneLength  geneStrand  geneId  distanceToTSS
chr2    1711333 1711568 236 *   ID=SRX067411;Name=H3K27ac%20(@%20HMEC);Title=GSM733660:%20Bernstein%20HMEC%20H3K27ac;Cell%20group=Breast;<br>source_name=HMEC;biomaterial_provider=Lonza;lab=Broad;lab%20description=Bernstein%20-%20Broad%20Institute;datatype=ChipSeq;datatype%20description=Chromatin%20IP%20Sequencing; 447 Intron (uc002qxa.3/7837, intron 1 of 22)    1   1635659 1748291 112633  2   7837    36723

이 문제를 해결하도록 도와주거나 조언을 줄 수 있는 사람이 있나요? 저는 Bash를 처음 접했고 이러한 명령에 익숙하지 않습니다.

지금까지 몇 가지 파일을 정리했습니다.

cut --complement -f 9-14 hisHMECanno.tsv | sed 's/%20/ /g' > hisHMECannoFilt.tsv

(원본 파일에는 불필요한 열이 몇 개 있어서 방금 제거했습니다.)

그런 다음 awk를 사용하여 항목을 탭으로 구분된 열로 분리하려고 계속 시도했지만 소용이 없었습니다.

답변1

다음 Perl 스크립트는 다음을 사용합니다.텍스트::CSV모듈은 TSV 파일을 읽고 올바른 형식의 TSV 데이터를 출력합니다.

필요한 경우 자동으로 필드를 인용하고 Text::CSV설정을 사용하여 undef_str정의되지 않은 메타데이터 필드를 인용된 빈 문자열로 출력합니다 ( 또는 ""로 인쇄하는 방법에 대한 주석 처리된 예 포함 ).N/A--

이 세 줄 중 최대 한 줄은 주석 처리를 제거해야 하며, 나머지 줄은 삭제하거나 주석 처리해야 합니다. 이 필드를 비워 두려면 세 줄을 모두 삭제/주석 처리하세요.

정의되지 않은 필드에 뭔가를 추가하는 것이 좋습니다. 이렇게 하면 두 개 이상의 탭(예: 빈 필드)을 단일 탭과 동일하게 처리할 수 있는 다른 도구를 사용하여 이 스크립트의 출력을 후처리하는 것이 더 쉬워지기 때문입니다(예: 필드 구분 기호를 기본 "공백 수 제한" 대신 단일 탭으로 명시적으로 설정하지 않는 한 기본적으로 이 작업을 수행 awk합니다 .perl

Text::CSV데비안 및 관련 배포판용으로 libtext-csv-perl(순수한 Perl 버전) 및 libtext-csv-xs-perl(더 빠르게 컴파일된 C 모듈) 로 패키지되어 있습니다. 를 사용하세요 apt install libtext-csv-perl. 다른 배포판에서도 이를 패키징할 수 있습니다. 그렇지 않으면 를 사용하십시오 cpan.

#!/usr/bin/perl

use strict;
use Text::CSV qw(csv);

my $csv=Text::CSV->new({sep_char => "\t", quote_space => 0});

# optional: define how to print undefined fields
#$csv->undef_str ('--');
#$csv->undef_str ('N/A');
$csv->undef_str ('""');

# get header line, split into an arrayref called $cols
my $cols = $csv->getline(*ARGV);

# get first data row, extract headers & data from metadata field
my $row = $csv->getline(*ARGV);

# The following line assumes that the metadata in the FIRST data row
# contains ALL of the metadata fields in the exact order you want them
# included in the output.
#
my $md_headers = extract_metadata_headers($$row[4]);
#
# If this is not the case, then delete the extract_metadata_headers
# subroutine and define the metadata fields manually with something
# like:
#
#my $md_headers = [
#  'ID', 'Name', 'Title', 'Cell group', 'source_name',
#  'biomaterial_provider', 'lab', 'lab description', 'datatype',
#  'datatype description', 'cell organism', 'cell description',
#  'cell karyotype', 'cell lineage', 'cell sex',
#  'antibody antibodydescription'
#];
# This defines both the extra metadata headers **and** the order
# that they will be included in each output row.

# extract the data from the metadata field
my $md_data = extract_metadata($$row[4]);

# replace the metadata header in $cols aref with the md headers
splice @$cols,4,1,@$md_headers;

# replace the metadata field in $row aref with the md fields
splice @$row,4,1,@$md_data;

# print the updated header line and the first row of data
$csv->say(*STDOUT,$cols);
$csv->say(*STDOUT,$row);

# main loop: extract and print the rest of the data
while (my $row = $csv->getline(*ARGV)) {
  my $md_data = extract_metadata($$row[4]);
  splice @$row,4,1,@$md_data;

  $csv->say(*STDOUT,$row);
}

###
### subroutines
###

sub extract_metadata_headers {
  my $md = clean_metadata(shift);
  my @metadata = split /;/, $md;
  my @headers=();

  foreach (@metadata) {
    next if m/^\s*$/; # skip empty metadata
    my ($key,$val) = split /=/;
    push @headers, $key;
  };

  return \@headers;
};

sub extract_metadata {
  my $md = clean_metadata(shift);
  my @metadata = split /;/, $md;
  my %data=();

  foreach (@metadata) {
    next if m/^\s*$/; # skip empty metadata
    my ($key,$val) = split /=/;
    $data{$key} = $val;
  };

  return [@data{@$md_headers}];
};

sub clean_metadata {
    my $md = shift;
    $md =~ s/%(\d\d)/chr hex $1/eg; # decode %-encoded spaces etc.
    $md =~ s/<[^>]*>//g;            # remove HTML crap like <br>
    return $md;
};

예를 들어 process-tsv.pl, 이를 실행 가능하게 만들고 chmod +x process-tsv.pl실행할 때 파일 이름 인수를 제공하십시오. 예를 들어

$ ./process-tsv.pl filename.tsv

stdout에 다음 출력이 생성됩니다.

$ ./process-tsv.pl input.tsv
seqnames        start   endwidth        strand  ID      Name    Title   Cell group      source_name     biomaterial_provider    lab     lab description datatype        datatype description    cell organism   cell description      cell karyotype   cell lineage    cell sex        antibody antibodydescription    X.10logMacsq    annotation      distanceToTSS
seq1    1       10      X       SRX067411       H3K27ac (@ HMEC)        GSM733660: Bernstein HMEC H3K27ac       Breast  HMEC    Lonza   Broad   Bernstein - Broad Institute     ChipSeq Chromatin IP Sequencing human   mammary epithelial cells       normal  ectoderm        U       rabbit polyclonal. Antibody Target: H3K27ac     x10     annot   dist
seq2    2       20      Y       SRX067411       H3K27ac (@ HMEC)        GSM733660: Bernstein HMEC H3K27ac       ""      ""      Lonza   Broad   Bernstein - Broad Institute     ChipSeq Chromatin IP Sequencing human   mammary epithelial cells       normal  ectoderm        U       ""      Y10     annot2  dist2

물론 출력을 셸의 파일로 리디렉션할 수 있습니다.

./process-tsv.pl input.tsv > output.tsv

답변2

모든 Unix 시스템의 쉘에서 awk를 사용하면 아마도 이것이 수행되기를 원할 것입니다. 그러나 추측을 테스트하는 데 사용할 수 있는 샘플 입력/출력은 없습니다.

$ cat tst.awk
BEGIN { FS=OFS="\t" }
{
    gsub(/%20/," ")
    gsub(/<br>/,"")
}
NR==1 {
    hdr = $0
    next
}
NR==2 {
    orig = $0
    gsub(/=[^=;]+;/,OFS,$6)
    sub(OFS"$","",$6)
    tags = $6
    $0 = hdr
    $6 = tags
    print
    $0 = orig
}
{
    gsub(/[^=;]+=/,OFS,$6)
    sub("^"OFS,"",$6)
    gsub(/;/,"",$6)
    print
}

$ awk -f tst.awk file
>       seqnames        start   endwidth        strand  ID      Name    Title   Cell group      source_name     biomaterial_provider    lab     lab description datatype        datatype description    cell organism   cell description        cell karyotype  cell lineage    cell sex        antibody antibodydescription    X.10logMacsq    annotation      distanceToTSS
>       foo     bar     etc     anon    SRX067411       H3K27ac (@ HMEC)        GSM733660: Bernstein HMEC H3K27ac       Breast  HMEC    Lonza   Broad  Bernstein - Broad Institute      ChipSeq Chromatin IP Sequencing human   mammary epithelial cells        normal  ectoderm        U       rabbit polyclonal. Antibody Target: H3K27ac     end     more    stuff

위의 내용은 다음 입력 파일을 사용하여 실행되었습니다.

$ cat file
>       seqnames        start   endwidth        strand  metadata        X.10logMacsq    annotation      distanceToTSS
>       foo     bar     etc     anon    ID=SRX067411;Name=H3K27ac%20(@%20HMEC);Title=GSM733660:%20Bernstein%20HMEC%20H3K27ac;Cell%20group=Breast;<br>source_name=HMEC;biomaterial_provider=Lonza;lab=Broad;lab%20description=Bernstein%20-%20Broad%20Institute;datatype=ChipSeq;datatype%20description=Chromatin%20IP%20Sequencing;cell%20organism=human;cell%20description=mammary%20epithelial%20cells;cell%20karyotype=normal;cell%20lineage=ectoderm;cell%20sex=U;antibody%20antibodydescription=rabbit%20polyclonal.%20Antibody%20Target:%20H3K27ac;       end     more    stuff

그 안의 모든 공백은 탭 문자입니다.

column다음을 사용하여 테이블로 시각화하여 값이 레이블(열 머리글 문자열)과 어떻게 정렬되는지 확인할 수 있습니다.

입력하다:

$ column -s$'\t' -t file
>  seqnames  start  endwidth  strand  metadata                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           X.10logMacsq  annotation  distanceToTSS
>  foo       bar    etc       anon    ID=SRX067411;Name=H3K27ac%20(@%20HMEC);Title=GSM733660:%20Bernstein%20HMEC%20H3K27ac;Cell%20group=Breast;<br>source_name=HMEC;biomaterial_provider=Lonza;lab=Broad;lab%20description=Bernstein%20-%20Broad%20Institute;datatype=ChipSeq;datatype%20description=Chromatin%20IP%20Sequencing;cell%20organism=human;cell%20description=mammary%20epithelial%20cells;cell%20karyotype=normal;cell%20lineage=ectoderm;cell%20sex=U;antibody%20antibodydescription=rabbit%20polyclonal.%20Antibody%20Target:%20H3K27ac;  end           more        stuff

산출:

$ awk -f tst.awk file | column -s$'\t' -t
>  seqnames  start  endwidth  strand  ID         Name              Title                              Cell group  source_name  biomaterial_provider  lab    lab description              datatype  datatype description     cell organism  cell description          cell karyotype  cell lineage  cell sex  antibody antibodydescription                 X.10logMacsq  annotation  distanceToTSS
>  foo       bar    etc       anon    SRX067411  H3K27ac (@ HMEC)  GSM733660: Bernstein HMEC H3K27ac  Breast      HMEC         Lonza                 Broad  Bernstein - Broad Institute  ChipSeq   Chromatin IP Sequencing  human          mammary epithelial cells  normal          ectoderm      U         rabbit polyclonal. Antibody Target: H3K27ac  end           more        stuff

답변3

사용밀러

$ mlr --tsv put -S '
    $metadata = gsub($metadata,"%20"," "); $metadata = gsub($metadata,"<br>|;$","")
  ' then put -S '
  $* = mapsum($*,splitkvx($metadata,"=",";"))
' then cut -x -f metadata HisHMECanno.tsv
seqnames        start   end     width   strand  X.10logMacsq    annotation      geneChr geneStart       geneEnd geneLength                                                 geneStrand       geneId  distanceToTSS   ID      Name    Title   Cell group      source_name     biomaterial_provider   lab                                                 lab description  datatype        datatype description
chr2    1711333 1711568 236     *       447     Intron (uc002qxa.3/7837, intron 1 of 22)        1       1635659 1748291                                                    112633   2       7837    36723   SRX067411       H3K27ac (@ HMEC)        GSM733660: Bernstein HMEC H3K27ac       Breast HMEC                                                Lonza    Broad   Bernstein - Broad Institute     ChipSeq Chromatin IP Sequencing

이 두 put명령을 합쳐도 되지만, '데이터 정리' 단계와 '필드 분할' 단계로 분리하는 것이 더 명확할 것 같습니다.

더 명확한 필드 분할을 위해 출력 형식을 CSV로 변경합니다.

mlr --itsv --ocsv put -S '
  $metadata = gsub($metadata,"%20"," "); $metadata = gsub($metadata,"<br>|;$","")
' then put -S '
  $* = mapsum($*,splitkvx($metadata,"=",";"))
' then cut -x -f metadata HisHMECanno.tsv
seqnames,start,end,width,strand,X.10logMacsq,annotation,geneChr,geneStart,geneEnd,geneLength,geneStrand,geneId,distanceToTSS,ID,Name,Title,Cell group,source_name,biomaterial_provider,lab,lab description,datatype,datatype description
chr2,1711333,1711568,236,*,447,"Intron (uc002qxa.3/7837, intron 1 of 22)",1,1635659,1748291,112633,2,7837,36723,SRX067411,H3K27ac (@ HMEC),GSM733660: Bernstein HMEC H3K27ac,Breast,HMEC,Lonza,Broad,Bernstein - Broad Institute,ChipSeq,Chromatin IP Sequencing

답변4

이는 정규식 및 목록 이해와 결합된 Python 사전 및 목록 데이터 구조를 사용하여 수행할 수 있습니다.

python3 -c 'import sys, re
ifile = sys.argv[1]
fs,rs = ofs,ors = "\t","\n"
with open(ifile) as f:
  for nr,l in enumerate(f,1):
    F = l.rstrip(rs).split(fs)
    if nr == 1:
      H = F
      idx_md = F.index("metadata")
      continue
    md_hdrs = re.findall(r"[^=;]+(?==)",F[idx_md])
    md = dict(t.split("=") for t in re.sub(r";+$","",F[idx_md]).split(";"))
    if nr == 2:
      print(*H[:idx_md], *md_hdrs, *H[idx_md+1:], sep=ofs)
    print(*F[:idx_md], *[md.get(key,"") for key in md_hdrs], *F[idx_md+1:], sep=ofs)
' file

산출:

seqnames    start   end width   strand  ID  Name    Title   Cell%20group    <br>source_name biomaterial_provider    lab lab%20description   datatype    datatype%20description  X.10logMacsq    annotation  geneChr geneStart   geneEnd geneLength  geneStrand  geneId  distanceToTSS
chr2    1711333 1711568 236 *   SRX067411   H3K27ac%20(@%20HMEC)    GSM733660:%20Bernstein%20HMEC%20H3K27ac Breast  HMEC    Lonza   Broad   Bernstein%20-%20Broad%20Institute   ChipSeq Chromatin%20IP%20Sequencing 447 Intron (uc002qxa.3/7837, intron_1_of_22)    1   1635659 1748291 112633  2   7837    36723

관련 정보