Unix - eliminer des colonnes .txt
Résolu
AlexMac
-
AlexMac -
AlexMac -
Bonjour a tous,
J'ai en input un fichier texte contenant
--at-gg---
--at-gga--
--at-gtcg-
--atgtgtt-
et je voudrais eliminer les colonnes contenant plus de 80% de -, afin d'obtenir :
atgg--
atgga-
atgtcg
attgtt
J'ai cherche beaucoup mais rien trouve. Peut etre la commande awk pour compter es occurences de - dans chaque colonne, mais je ne vois pas comment faire
Merci pour votre aide
Alexandre
J'ai en input un fichier texte contenant
--at-gg---
--at-gga--
--at-gtcg-
--atgtgtt-
et je voudrais eliminer les colonnes contenant plus de 80% de -, afin d'obtenir :
atgg--
atgga-
atgtcg
attgtt
J'ai cherche beaucoup mais rien trouve. Peut etre la commande awk pour compter es occurences de - dans chaque colonne, mais je ne vois pas comment faire
Merci pour votre aide
Alexandre
4 réponses
-
hello
la colonne 5 contient moins de 80% de -, c'est pour cela que je teste <75$ cat a1 --at-gg--- --at-gga-- --at-gtcg- --atgtgtt- $ $ awk '{x[NR]=$0}END{for(i=1;i<=10;i++){for(n=1;n<=NR;n++){if(substr(x[n],i,1)=="-")c[i]++} ;col[i]=(100*c[i])/NR} ; for(n=1;n<=NR;n++){for(i=1;i<=10;i++){if(col[i]<75)printf substr(x[n], i, 1)} print ""}}' a1 atgg-- atgga- atgtcg attgtt $ $-
-
même code, mais dans un fichjier avec indentations
# on lit le fichirer en entier qu'on stocke dans un tableau x {x[NR]=$0} END{ # pour chaque colonne (ici 10) de chaque ligne (NR == nb de lignes), on # compte le nombre de -, nombre que l'on stocke dans un tableau c for(i=1;i<=10;i++){ for(n=1;n<=NR;n++){ if(substr(x[n],i,1)=="-") c[i]++} ; # on a le nombre de - par colonne, on peut calculer le % col[i]=(100*c[i])/NR } ; # pour chaque ligne et chaque colonne, on teste si le % de cette colonne # est < 75, si oui on imprime le caractère for(n=1;n<=NR;n++){ for(i=1;i<=10;i++){ if(col[i]<75) printf substr(x[n], i, 1) } # on imprime un saut de ligne en fin de ligne print "" } }
-
-
En fait si je résume cette longue discussion c'est que le pourcentage seuil (80%) est relatif à chaque colonne, ce qui force à lire l'ensemble des lignes pour savoir si la colonne est conservée ou non.
À mon avis il n'y a pas quarante solutions, il faut lire toutes les lignes, les stocker en mémoire, et parcourir la structure ainsi lue. A peu près n'importe quel langage de programmation permet de le faire.
Personnellement je fais plutôt du C++, mais si tu préfères le python ou n'importe quoi d'autre pourquoi pas...
Source (toto.cpp)#include <fstream> #include <vector> #include <iostream> #include <string> int main(int argc, char **argv){ const char *filename_in = argv[1], *filename_out = argv[2]; const unsigned int num_chars = 10; // Chaque ligne valide doit comporter 10 caractères const unsigned int threshold = 80; // 80 % unsigned int num_lines = 0; std::string line; std::ifstream ifs; std::ofstream ofs; std::vector<std::string> lines; std::vector<unsigned int> num_minus(num_chars, 0); std::vector<bool> column_to_write(num_chars); if(argc != 3) { std::cerr << "usage: " << argv[0] << " input_file output_file" << std::endl; goto END; } // Ouvrir le fichier d'entrée ifs.open(filename_in); if(!ifs) { std::cerr << argv[0] << ": can't read " << filename_in << std::endl; goto END; } // Ouvrir le fichier de sortie ofs.open(filename_out); if(!ofs) { std::cerr << argv[0] << ": can't write " << filename_out << std::endl; goto END; } // Charger les lignes en mémoire et compter le nombre de '-' while(std::getline(ifs, line)) { if(line.size() == num_chars){ for(std::size_t i = 0; i < num_chars; ++i){ if(line[i] == '-') ++num_minus[i]; } lines.push_back(line); ++num_lines; } } // Quelles colonnes doit on réécrire ? for(std::size_t i = 0; i < num_chars; ++i){ column_to_write[i] = ((100 * num_minus[i] / num_lines) < threshold); } // Écrire les lignes en ne conservant que le nécessaire for(std::size_t i = 0; i < lines.size(); ++i){ for(std::size_t j = 0; j < num_chars; ++j){ if(column_to_write[j]){ ofs << lines[i][j]; } } ofs << std::endl; } END: // On ferme proprement if(ifs) ifs.close(); if(ofs) ofs.close(); return 0; }
Avec ce fichier d'entrée (input.txt) :
--at-gg--- --at-gga-- --at-gtcg- --atgtgtt-
Il faut à présent installer un compilateur (par exemple g++ sous linux ou code::blocks sous windows). Par exemple sous linux (ubuntu, debian...) :
sudo apt-get update sudo apt-get install g++
On compile notre programme (appelons le par exemple convertir.exe) :
(mando@aldur) (~) $ g++ -W -Wall toto.cpp -o convertir.exe (mando@aldur) (~) $ ./convertir input.txt output.txt
On obtient le fichier output.txt :
at-gg-- at-gga- at-gtcg atgtgtt
... ce qui est le bon résultat si j'ai bien pigé.
À l'époque tu avais dit que normalement la sortie était :
atgg-- atgga- atgtcg attgtt
... mais la colonne qui contient (-,-,-,g) contient seulement 75% de '-' soit moins de 80%, donc normalement on la conserve...
Bonne chance -
Salut,
Rien pigé à ton histoire de 80% ;-((
Sur la ligne 2, pourquoi t'élimines les 2 premiers et qu'un seul sur les 2 derniers ???--at-gga-- => atgga-
-
En fait il faut lire en colonne :
la premiere colonne ne contient que des - (donc 100% de -), elle degage
la deuxieme idem
la troisieme ne contient pas de - (il n'a que des a), elle reste
etc
l'avant dernier ne contient que deux - (et un g et un t), donc elle reste (50% de -)
et la derniere ne contient que des -, elle degage
J'espere avoir reussi a etre clair cette fois
Merci
Alex -
-
-
Tes explications sont complètement incohérentes ;-((
la premiere colonne ne contient que des - (donc 100% de -), elle degage
la deuxieme idem
En considérant que chaque caractère est en fait une colonne à lui tout seul, nous sommes d'accord ;-\
la troisieme ne contient pas de - (il n'a que des a), elle reste
etc
Idem qu'au-dessus ;-\
l'avant dernier ne contient que deux - (et un g et un t), donc elle reste (50% de -)
C'est là où ça se corse ;-((
Pourquoi subitement ta colonne contient plusieurs caractères et commence à mélanger caractères alphanumériques avec des caractères non-alphanumériques ???
Où est la logique dans tout ça ??? ;-\ -
il s'agit de sequences d'ADN (succession de molecules A T C et G pour Adenosine, Guanine, Thymine, Custeine) qui sont alignees selon leur similarite, imaginons:
gene humain ATGCT - -TCGCT
gene mouche ATGCTTGTCGCT
gene meduse ATCGT - -TCGCT
Ces genes sont identiques chez les trois organismes (humain, mouche , meduse), sauf que dans la sequence genetique de la mouche, il y a deux molecules en plus, un T et un G.
Ce molecules absente chez l'homme et la meduse sont representes par des tirets.
Ce que je voudrais c'est conserver cet alignement tou en eliminant les zones contenant beaucoup de tirets, c'est a dire les zones genetiques peu conservees entre differentes especes.
Voila, j'espere que c'est plu clair pour toi
Alex
-
-
Oui tu peux t'en sortir avec awk.
man awk
$0 désigne la ligne courante, affecte là à s.
length(s) permet de calculer la longueur de s.
Crée un compteur (par exemple num_minus) initialisé à 0.
Dans une boucle for allant de 0 à length(s) - 1 :
- substr(s, i, 1) permet d'extraire le i-ème caractère.
- si c'est un tiret, incrémente ton compteur num_minus
Une fois la boucle for, calcule le pourcentage (100 * num_minus / length(s)). S'il est supérieur à ton seuil de 80, print $0.
Bonne chance