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
A voir également:
- Unix - eliminer des colonnes .txt
- Comment faire des colonnes sur word - Guide
- Classer par ordre alphabétique excel plusieurs colonnes - Guide
- Déplacer des colonnes excel - Guide
- Dans le fichier, générez ce tableau automatiquement (tableau croisé dynamique ou table de pilote) à partir des quatre premières colonnes. - Guide
- Figer des colonnes excel - Guide
4 réponses
hello
la colonne 5 contient moins de 80% de -, c'est pour cela que je teste <75
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
$
$
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)
Avec ce fichier d'entrée (input.txt) :
Il faut à présent installer un compilateur (par exemple g++ sous linux ou code::blocks sous windows). Par exemple sous linux (ubuntu, debian...) :
On compile notre programme (appelons le par exemple convertir.exe) :
On obtient le fichier output.txt :
... ce qui est le bon résultat si j'ai bien pigé.
À l'époque tu avais dit que normalement la sortie était :
... mais la colonne qui contient (-,-,-,g) contient seulement 75% de '-' soit moins de 80%, donc normalement on la conserve...
Bonne chance
À 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 ???
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
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 ??? ;-\
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
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.
$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
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
Ca marche a merveille!
Je vais essayer de décortiquer pour comprendre, mais j'avoue que quelques explication seraient les bienvenues.
Merci encore beaucoup
Alex
# 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 "" } }