Удаление дублирующихся строк в .tsv с сохранением некоторых данных (bash, perl) - PullRequest
0 голосов
/ 19 марта 2020

У меня есть несколько больших файлов .tsv, таких как:

rownbr     pos      pvalue   percentage    samplename
1      chr1_12000    0.05       5.6            S1
1      chr1_12500    0.04       15.9           S1
3      chr1_12570    0.9        45.3           S2
2      chr1_12500    0.03       13.8           S3

Я хотел бы удалить дубликаты строк на основе столбца pos , сохраняя при этом значения обеих строк для столбцов 3 и 5 , чтобы выходные данные могли выглядеть примерно так:

rownbr     pos      pvalue   percentage    samplename
1      chr1_12000    0.05       5.6            S1
1      chr1_12500    0.04,0.03  15.9           S1,S3
3      chr1_12570    0.9        45.3           S2

Моя идея состояла в том, чтобы сначала отсортировать файлы .tsv, используя shell sort function:

sort -k 2,2 *.tsv

А затем напишите скрипт, который будет сравнивать каждую строку со следующей строкой. Если строка в столбце pos одинакова для обеих строк, то она объединит значения столбцов 3 и 5 в строке n + 1 со значениями в строке п . Однако я понятия не имею, как это сделать.

Я знаком с awk / sed / grep / bash, но у меня также есть некоторые (ограниченные) perl основы.

Спасибо за ваше помогите!

Ответы [ 4 ]

3 голосов
/ 19 марта 2020

Вот пример того, как вы можете подойти к нему в Perl:

use feature qw(say);
use strict;
use warnings;

my $fn = 'file1.tsv';
open ( my $fh, '<', $fn ) or die "Could not open file '$fn': $!";
my $header = <$fh>;
my @pos;
my %info;
while( my $line = <$fh> ) {
    chomp $line;
    my ($nbr, $pos, $pvalue, $percentage, $samplename) = split /\t/, $line;
    if ( !exists $info{$pos} ) {
        $info{$pos} = {
            nbr        => $nbr,
            pvalue     => [$pvalue],
            percentage => $percentage,
            samplename => [$samplename],
        };
        push @pos, $pos;
    }
    else {
        push @{$info{$pos}{pvalue}}, $pvalue; 
        push @{$info{$pos}{samplename}}, $samplename; 
    }
}    
close $fh;

print $header;
for my $pos (@pos) {
    my $data = $info{$pos};
    say join "\t", $data->{nbr}, $pos,
      (join ",", @{$data->{pvalue}}), $data->{percentage},
      (join ",", @{$data->{samplename}});
}

Вывод :

rownbr     pos      pvalue   percentage    samplename
1   chr1_12000  0.05    5.6 S1
1   chr1_12500  0.04,0.03   15.9    S1,S3
3   chr1_12570  0.9 45.3    S2
1 голос
/ 19 марта 2020

Используя комбинацию GNU datamash и awk, чтобы получить только нужные столбцы:

$ datamash --header-in -sf -g2 collapse 3,5 < input.tsv | \
  awk 'BEGIN { FS=OFS="\t"; print "rownbr\tpos\tpvalue\tpercentage\tsamplename" }
       { print $1, $2, $6, $4, $7 }'
rownbr  pos pvalue  percentage  samplename
1   chr1_12000  0.05    5.6 S1
1   chr1_12500  0.04,0.03   15.9    S1,S3
3   chr1_12570  0.9 45.3    S2

Игнорировать строку заголовка в файле (--header-in), группировать записи во втором столбце (-g2), сортировать по этому столбцу (-s), выводить полную строку (- f) в дополнение к заданным операциям, а также для 3-го и 5-го столбцов , сверните все строки группы в одну запись CSV. Чтобы использовать нужные столбцы в правильном порядке, используйте awk.

1 голос
/ 19 марта 2020

файл "myscript":

#! /usr/bin/env bash

file="$1"

result="$(tr -s '\t' < "${file}"  | tail -n +2 |
        awk -F'\t' -v OFS='\t' '

        $0 == "" {
            next
        }

        # MAIN 
        {
            if (col3[$2] == "") {
                col1[$2] = $1
                col3[$2] = $3
                col4[$2] = $4   
                col5[$2] = $5
            } else {
                col3[$2] = col3[$2]","$3
                col5[$2] = col5[$2]","$5
            }
        }

        END {

            for (pos in col1) {
                print col1[pos], pos, col3[pos], col4[pos], col5[pos]
            }
        }
        ' | sort -k 2,2 )"

first_line="$(head -n 1 "${file}")"
echo "${first_line}"
echo "${result}"

Запустите его как:

bash myscript <your tsv file>

Результат будет записан в стандартный вывод.

0 голосов
/ 19 марта 2020

Perl идеальный инструмент для этой задачи.

сохранить заголовок данных для будущего вывода.

извлекать pos поле для использования в качестве га sh ключ

сохранить строку в га sh если мы не видели этого pos раньше, в противном случае объединяем значение и имя в строку.

После того, как все строки обработаны, выведите результат (в этом случае я использую 'format' и напишем)

use strict;
use warnings;
use feature 'say';

my(@pos,%seen,%lines);
my $header = <DATA>;                            # obtain header

chomp $header;

while(<DATA>) {
    next if /^\s*$/;                            # skip empty lines

    chomp;

    my $key = (split '\s+')[1];                 # extract 'pos' to use as $key

    if( $seen{$key} ) {
        my($value,$name) = (split '\s+')[2,4];  # extract value and name
        $lines{$key} =~ s/(\d\s+\S+\s+\S+)/$1,$value/;  # merge value
        $lines{$key} =~ s/$/,$name/;            # merge name
    } else {
        push @pos, $key;                        # preserve order
        $lines{$key} = $_;                      # store lines in a hash
        $seen{$key} = 1;
    }
}


say $header;                                    # output header

my @data;

for (@pos) {                                    # use stored hash 'indexes'
    @data = split '\s+',$lines{$_};             # split into fields
    write;                                      # output
}

# format STDOUT_HEADER = 
# rownbr     pos      pvalue   percentage    samplename
# .

format STDOUT = 
@<<<<< @<<<<<<<<<    @<<<<<<<<  @<<<<<         @<<<<<<<<<<<<
$data[0],$data[1],$data[2],$data[3],$data[4]
.

__DATA__
rownbr     pos      pvalue   percentage    samplename
1      chr1_12000    0.05       5.6            S1
1      chr1_12500    0.04       15.9           S1
3      chr1_12570    0.9        45.3           S2
2      chr1_12500    0.03       13.8           S3

Выход

rownbr     pos      pvalue   percentage    samplename
1      chr1_12000    0.05       5.6            S1
1      chr1_12500    0.04,0.03  15.9           S1,S3
3      chr1_12570    0.9        45.3           S2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...