compara dados em dois arquivos um tem 2 colunas enquanto outro tem 3 colunas

2

Eu tenho dois arquivos:

Arquivo 1:

Chromosome   Position
Chr1    5242097
Chr1    4876397
Chr1    9474943
Chr1    8494518
Chr1    39872693
Chr1    9445153
Chr1    23044399
Chr1    8018859
Chr1    9474943
Chr1    42380010
Chr1    9474943
Chr1    22677151
Chr1    23044399
Chr1    42380010

Arquivo 2:

Chr1    1   0
Chr1    2   0
Chr1    3   0
Chr1    4   0
Chr1    5   0
Chr1    6   0
Chr1    7   0
Chr1    8   0
Chr1    9   0
Chr1    10  0
Chr1    11  0
Chr1    12  0
Chr1    13  0
Chr1    14  0
Chr1    15  0
Chr1    16  0
Chr1    17  0
Chr1    18  0
Chr1    19  0
Chr1    20  0
Chr1    21  0
Chr1    22  0
Chr1    23  0
Chr1    24  0
Chr1    25  0
Chr1    26  0
Chr1    27  0
Chr1    28  0
Chr1    29  0
Chr1    30  0
Chr1    31  0
Chr1    32  0
Chr1    33  0
Chr1    34  0
Chr1    35  0
Chr1    36  0
Chr1    37  0
Chr1    38  0
Chr1    39  0
Chr1    40  0
Chr1    41  0
Chr1    42  0
Chr1    43  0
Chr1    44  0
Chr1    45  0
Chr1    46  0
Chr1    47  0
Chr1    48  0
Chr1    49  0
Chr1    50  0

O File2 é muito grande, por isso não mostro a coisa toda. Os números podem subir para mais de 6 dígitos.

Eu quero buscar a terceira coluna do arquivo2 se ela corresponder à segunda coluna do arquivo1.

Eu escrevi um programa Perl, mas é muito lento. Eu estou procurando uma maneira rápida de fazer isso. Grep também é lento.

    
por rashmi 15.09.2015 / 19:38

5 respostas

3

Eu escreveria

awk '
    # store column 2 from the first file
    NR == FNR {pos[$2] = 1; next}

    # from the second file, print the 3rd field if it occurred in file1
    $3 in pos {print $3}
' file1 file2
    
por 15.09.2015 / 20:31
2

Mantenha apenas col2 do arquivo 1

awk '{print $2}' file1 > file1_col2

Em seguida, mantenha a col3 do arquivo2:

awk '{print $3}'  file2> file2_col3

Agora pesquise por ocorrências de linhas file1_col2 no arquivo2_col3:

grep -f file1_col2 file2_col3
    
por 15.09.2015 / 20:05
2

Se lento, o C ++ deve ajudar, seriamente, pode ser usado para escrever coisas rápidas também =). Salve em file.cc e compile com g++ file.cc -O2 -o file , execute como ./file no diretório com o arquivo; substitua firstfilename e o segundo nome de arquivo que você precisa antes da compilação.

Você não conseguirá bater C ++ em velocidade =)

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main() {
   ifstream f1("firstfilename"), f2("secondfilename");
   string s;
   int i1, i2, line=0;
   while (!f1.eof()) {
      line++;
      if (f2.eof()) {
         cout << "Length different!" << "\n";
      }
      f1>>s>>i1;
      f2>>s>>i2>>i2;
      if (i1 != i2) {
         cout << "Not matching line " << line << " " << i1 << "<>" << i2 << "\n";
      }
   }
}
    
por 15.09.2015 / 20:28
1

Se o seu primeiro arquivo é pequeno o suficiente para caber na memória, você pode fazer isso em Perl:

perl -e 'open($f1,"file1"); while(<$f1>){chomp; $k{$_}++}
         while(<>){ /(.+?\s+.+?)\s/; print if defined($k{$1})' file2

Isso deve ser razoavelmente rápido, mas ainda precisa ler todo o file2 .

    
por 15.09.2015 / 23:38
1

Use join , inclua sort se seus dados não forem classificados pelo campo apropriado.

join -1 2 -2 3 -o 2.3 <(sort -k2,2 file1) <(sort -k3,3 file2)

Se sort não for necessário:

join -1 2 -2 3 -o 2.3 file1 file2

Isso está usando utilitários GNU. Para outras variantes, eu precisaria saber qual Unix você está usando. A versão acima com sort é mostrada com a substituição do processo Bash, que também funciona em algumas outras camadas.

Como o campo de junção também é o campo de saída, -o 2.3 pode ser simplificado para -o 0 .

    
por 16.09.2015 / 00:30