J'ai deux fichiers, un avec une liste complète des noms de gènes et trois autres avec des listes partielles de noms de gènes. Je veux faire correspondre ces fichiers en un seul. Tous les fichiers partiels ont un nombre de lignes différent mais ont 3000 colonnes , représentant tous des cellules différentes. J'ai essayé de joindre complètement ces fichiers, mais lorsque j'utilise awk, une seule colonne est conservée.

MergedAll.txt

GENE
SOX2
BRCA1
BRCA2
RHO

UltimatecontrolMed.txt

GENE     CELL1   CELL2   CELL3
SOX2     30      152     2000
BRCA2    400     234     73
RHO      12      2       0

Ma sortie souhaitée serait

GENE     CELL1   CELL2   CELL3
SOX2     30      152     2000
BRCA1    0       0       0
BRCA2    400     234     73
RHO      12      2       0

Je cours:

awk 'NR==FNR{k[$1];next}{b[$1]=$0;k[$1]}
END{for(x in k)
      if ( x== "GENE" )
         printf"%s %s\n",x,b[x]
      else
         printf"%s  %d\n",x,b[x]
}' mergedAll.txt ultimatecontrolMed.txt > test.txt

Et je reçois:

GENE CELL1 CELL 2 CELL3
SOX2 2000
BRCA1 0
BRCA2 73
RHO 0

Pour une raison quelconque, il conservera la dernière colonne de décomptes, mais aucune des autres lignes, et conservera tous les noms de cellules. Je n'ai aucune expérience avec awk, donc cela a été un défi majeur pour moi dans l'ensemble et j'aimerais beaucoup que quelqu'un puisse proposer une meilleure solution.

1
ap524 17 nov. 2017 à 21:12

4 réponses

Meilleure réponse

awk à la rescousse!

$ awk 'NR==FNR {a[$1]=$0; next} 
               {print (a[$1]?a[$1]:($1 FS 0 FS 0 FS 0))}' file2 file1 | 
  column -t

GENE   CELL1  CELL2  CELL3
SOX2   30     152    2000
BRCA1  0      0      0
BRCA2  400    234    73
RHO    12     2      0

Le tuyau final vers column est pour une jolie impression. Notez l'ordre des fichiers.

Ne pas coder en dur le nombre de colonnes que vous pouvez essayer cette alternative

$ awk 'NR==1   {for(i=2;i<=NF;i++) missing=missing FS 0}  
       NR==FNR {a[$1]=$0; next} 
               {print (a[$1]?a[$1]:($1 missing))}' file2 file1
1
karakfa 17 nov. 2017 à 18:35
join -a 1 -a 2 -e 0 -o 0 2.{2..4}  mergedAll.txt ultimatecontrolMed.txt

2.{2..4} imprime une liste de champs de sortie et peut facilement s'adapter à n'importe quel nombre de champs.

Comme vous mentionnez trois fichiers d'entrée, il serait possible de rediriger le résultat d'une première jointure dans un second

join .... file1 file2 | join ... file3 

join a besoin d'une entrée triée. Cela peut être un argument tueur pour cette solution.

0
ULick 19 nov. 2017 à 18:46

Pourriez-vous s'il vous plaît essayer de suivre awk et me faire savoir si cela vous aide.

awk 'FNR==NR{a[$0];next} ($1 in a){print;delete a[$1];next} END{for(i in a){print i,"0 0 0"}}' mergedAll.txt  ultimatecontrolMed.txt
0
RavinderSingh13 17 nov. 2017 à 18:25

Le problème est que vous imprimez b[x] au format %d. C'est pour imprimer un seul entier, donc il ignorera tous les autres entiers de b[x]. Changement

     printf"%s  %d\n",x,b[x]

À:

    if (b[x]) {
        printf "%s\t%s\n", x, b[x]
    } else {
        printf "%s" x;
        for (i = 0; i < 3000; i++) printf "\t0"
        print ""
    }

Afin qu'il imprime la valeur entière. S'il n'y a pas de valeur correspondante, il affichera des zéros.

Remplacez 3000 par le nombre approprié de cellules. Si vous ne voulez pas le coder en dur, vous pouvez l'obtenir à partir de NF-1 quand FNR == 1 && FNR != NR (la première ligne du deuxième fichier).

0
Barmar 17 nov. 2017 à 20:27
47356837