Imprime valores de uma coluna para outra entre dois arquivos baseados em padrões em cada linha

1

O arquivo 1 contém duas colunas. A coluna 1 tem nomes de vias metabólicas e a coluna 2 tem o número de genes presentes nessa via:

pathway1 3   
pathway2 4  
pathway3 5  
pathway4 6  
pathway5 9

O arquivo 2 tem três colunas. A coluna 1 tem o número do grupo, a coluna 2 tem nomes de vias metabólicas pertencentes a um grupo específico, a coluna 3 tem o número de genes presentes em cada via:

group1  pathway1  2   
group1  pathway4  5  
group1  pathway2  3  

group2  pathway2 1  
group2  pathway3 2 

Arquivo1 e Arquivo2 estão no formato csv.

Saída exigida:
Com base no nome do caminho, como posso imprimir o número de genes da coluna 2 do Arquivo1 ao lado da coluna 3 do Arquivo2, para que fique assim:

group1  pathway1 2 3   
group1  pathway4 5 6  
group1  pathway2 3 4  

group2  pathway2 1 4  
group2  pathway3 2 5 
    
por Saisha 09.03.2017 / 08:33

3 respostas

1

Isso deve ser suficiente no awk:

awk 'NR==FNR{a[$1]=$2;next}{print $0,a[$2]}' file1 file2

Seus arquivos de amostra são apresentados como separados por espaço e o código acima funcionará para arquivos separados por espaço.

Se o seu arquivo1 arquivo2 estiver separado por vírgula, você poderá fazer:

awk 'BEGIN{FS=OFS=","}NR==FNR{a[$1]=$2;next}{print $0,a[$2]}' file1 file2

PS: No awk FS corresponde ao separador de campo de entrada e OFS ao separador de campo de saída. O padrão FS e OFS é "espaço" e pode ser omitido se o espaço for o seu caso (ou seja, omitido no primeiro código)

Se você deseja combinar um separador de campo de entrada diferente e um separador de campo de saída diferente, poderá fazer algo assim:

awk 'BEGIN{FS=" ";OFS=","}NR==FNR{a[$1]=$2;next};$1=$1{print $0,a[$2]}' file1 file2 
#The $1=$1 part is required to redisign the record according to the different Output Field Separator OFS

O último código para arquivos de entrada separados por espaço (como exatamente aparece na sua pergunta) e saída com separação por vírgula fornecerá:

group1,pathway1,2,3                                                                                                                                                             
group1,pathway4,5,6                                                                                                                                                             
group1,pathway2,3,4                                                                                                                                                             
group2,pathway2,1,4                                                                                                                                                             
group2,pathway3,2,5

Teste on-line aqui.

PS: Para arquivos separados por espaço, você pode atribuir OFS="\t" (tab) para uma saída mais agradável.

    
por 09.03.2017 / 08:56
2

É para isso que join foi feito:

$ join -o 1.1,1.2,1.3,2.2 -12 -21 <(sort -k2 file2) <(sort file1) 
group1 pathway1 2 3
group2 pathway2 1 4
group1 pathway2 3 4
group2 pathway3 2 5
group1 pathway4 5 6

Ou, se os seus arquivos de entrada estiverem realmente separados por vírgulas, como sugere, mas não mostre, na sua pergunta:

$ join -t, -o 1.1,1.2,1.3,2.2 -12 -21 <(sort -t, -k2 file2) <(sort file1) 
group1,pathway1,2,3
group2,pathway2,1,4
group1,pathway2,3,4
group2,pathway3,2,5
group1,pathway4,5,6

join unirá linhas de dois arquivos em um campo comum. O -o define o formato de saída. Aqui, estou dizendo para imprimir os campos 1, 2 e 3 do primeiro arquivo ( 1.1,1.2,1.3 ), seguido pelo segundo campo do segundo arquivo ( 2.2 ). O -1 e -2 definem o campo de associação em cada arquivo. Portanto, -12 -21 significa "junte-se ao segundo campo do arquivo1 e o primeiro do arquivo2". Finalmente, join requer entrada classificada, então classificamos os dois arquivos antes de passá-los para join .

    
por 09.03.2017 / 09:55
1
perl -lane '
 if ( @ARGV == 1 ) {
  $h{ $F[0] } = $F[1];
 } else {
  print "$_ $h{ $F[1] }";
 }
' file1 file2
    
por 09.03.2017 / 08:40