1 de julio de 2010

A qué grupo taxonómico pertenece una especie?

Desde hace ya tiempo hay más secuencias genómicas disponibles que las que podemos recordar y a menudo nos encontramos con nombres de organismos que no podemos ubicar, no sabemos si son bacterias aguas termales o artrópodos, por ejemplo. El siguiente programa puede ayudarnos precisamente a colocar dentro de la clasificación taxonómica vigente del NCBI un nombre de especie, o en general, cualquier taxón de nombre aceptado. Antes de ejecutarlo debes acceder al servidor FTP en ftp://ftp.ncbi.nih.gov/pub/taxonomy y descomprimir los archivos de nombres y nodos, como se explica en la cabecera del código Perl, haciendo apuntar la variable global $TAXONOMYPATH al directorio donde se encuentren. Una vez hechos estos ajustes el código ya está listo para usarse desde el terminal. Por ejemplo, si consultamos la taxonomía de Oryza sativa obtendremos esta respuesta, que podemos comparar con la figura, tomada de www.biomedcentral.com/1471-2164/8/283:


$ ./prog6.pl Oryza sativa 

# input taxon: Oryza sativa

# selected taxonID: 4530 \\ 
   URL: http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?id=4530

# variants:
> Oryza sativa
> Oryza sativa L.

# lineage : Oryza sativa, Oryza, Oryzeae, Ehrhartoideae, BEP clade, Poaceae, 
Poales,commelinids, Liliopsida, Magnoliophyta, Spermatophyta, Euphyllophyta, 
Tracheophyta, Embryophyta, Streptophytina, Streptophyta, Viridiplantae, 
Eukaryota, cellular organisms

# rank : species, genus, tribe, subfamily, no_rank, family, order, subclass, 
class, no_rank, no_rank, no_rank, no_rank, no_rank, no_rank, phylum, kingdom, 
superkingdom, no_rank,

Éste es el código:

 #!/usr/bin/perl -w  
   
 # prog6  
 # programa que devuelve informacion taxonomica para un taxon de entrada,   
 # que se apoya en la version texto de la clasificacion Taxonomy del NCBI,   
 # que se pueden descargar de ftp://ftp.ncbi.nih.gov/pub/taxonomy , en   
 # particular el fichero taxdump.tar.gz, que debes descomprimir para obtener   
 # los dos ficheros que se utilizan aqui  
 # Bruno Contreras Moreira, Junio de 2010  
   
 use strict;  
 $|=1;  
   
 if(!$ARGV[0])  
 {   
    die "# usage: $0 <taxon name from superkingdom to species, such as:\n".  
    "       'Arabidopsis thaliana' or 'Viridiplantae' but not 'thaliana'>\n";   
 }  
   
 my $VERBOSE   = 0 ;  
 my $TAXONOMYPATH = '/path/taxonomy/'; # directorio de taxdump.tar.gz  
 my $NAMESFILE  = $TAXONOMYPATH . 'names.dmp';  
 my $NODESFILE  = $TAXONOMYPATH . 'nodes.dmp';  
 my $NCBIURL   = 'http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?id=';  
   
 ###################################################################  
   
 my ($n_of_taxa,$taxonID,$taxon,$ID,$name,$rank,$parentID) = (0,'','');  
 my (@names,%node,@lineage,@sorted_lineage,%lineage_name);  
 my ($lineage_names,$lineage_ranks) = ('','');  
   
 ## 1) captura el nombre del taxon de entrada, como Arabidopsis thaliana, y  
 ## sustituye caracteres '_' por espacios si los hubiera   
 if(scalar(@ARGV) > 1){ @ARGV = @ARGV[0,1]; } # corta tercera palabra < especie  
 else{ @ARGV = split(/_/,$ARGV[0]); @ARGV = @ARGV[0,1]; }  
   
 $taxon = join(' ',@ARGV);  
 $taxon =~ s/^\s+//g; # elimina espacios iniciales y finales  
 $taxon =~ s/\s+$//g;   
   
 print "# input taxon: $taxon\n\n";  
   
 ## 2) busca el taxonID del taxon de entrada  
 open(NAMES,$NAMESFILE) || die "# $0 : cannot open $NAMESFILE\n";  
 while(<NAMES>)  
 {  
    next if(!/$taxon/i);  
      
    #3702   |   Arabidopsis thaliana   |      |   scientific name  
    if(/^(\d+)\s+\|\s+(.*?)\|/)  
    {  
       ($ID,$name) = ($1,$2);   
       $name =~ s/^\s+//g;   
       $name =~ s/\s+$//g;   
            
       # comprueba que el taxon buscado coincide con el principio de $name,   
       # evita aceptar cadenas que en realidad coinciden con la especie,   
       # que a veces se pueden encontrar en generos muy distintos  
       next if(index($name,$taxon) != 0);  
         
       # si el taxon buscado contiene una sola palabra evita  
       # aceptar cadenas de especies, que tendran dos palabras  
       next if($taxon !~ /\s+/ && $name =~ /\s+/);  
            
       if(!$n_of_taxa || $ID eq $taxonID) # guarda primer taxonID   
       {  
          $taxonID = $ID;  
          push(@names,$name);  
          $n_of_taxa++;  
               
          if($VERBOSE){ print }  
       }  
       else  
       {  
          if($VERBOSE)  
          {   
             # muestra otras posibles apariciones del taxon  
             print "# skip taxon: $ID\n";   
          }     
          else{ last } # termina la lectura del fichero   
       }     
    }        
 }  
 close(NAMES);  
   
 if(!$n_of_taxa){ die "# cannot find taxon $taxon in $NAMESFILE , exit\n"; }  
 else  
 {   
    print "# selected taxonID: $taxonID  URL: $NCBIURL$taxonID\n";  
    print "\n# variants:\n";   
    foreach $name (@names){ print "> $name\n"; }  
 }  
   
 ## 3) busca taxon padre del taxonID encontrado  
 open(NODES,$NODESFILE) || die "# $0 : cannot open $NODESFILE\n";  
 while(<NODES>)  
 {  
    #132596   |   79512   |   genus...  
    #tax_id         -- node id in GenBank taxonomy database  
     #parent tax_id      -- parent node id in GenBank taxonomy   
     #rank         -- rank of this node (superkingdom, kingdom, ...)   
    next if(/forma/ || /varietas/); # evita rangos < especie  
    if(/^$taxonID\t/)  
    {  
       my @data = split(/\t|\t/,$_);  
       $parentID = $data[2];  
       $rank   = $data[4];   
       if($VERBOSE){ print }  
       last;  
    }  
 }  
 close(NODES);   
   
 if(!$parentID){ die "\n# cannot find taxon '$taxon' in $NODESFILE , exit\n"; }  
   
 ## 4) lee arbol taxonomico del nivel de especie hacia arriba   
 ## (son en 2010 35MB, caben en cualquier RAM)  
 open(NODES,$NODESFILE) || die "# $0 : cannot open $NODESFILE\n";  
 while(<NODES>)  
 {  
    next if(/forma/ || /varietas/);  
    if(/^(\d+)\t\|\t(\d+)\t\|\t(\S+)/)  
    {  
       $node{$1}{'p'} = $2; # p = parent node  
       $node{$1}{'r'} = $3; # r = rank  
    }  
 }  
 close(NODES);   
   
 ## 5) reconstruye linaje de $taxonID en terminos de IDs  
 # 5.1) primero guarda datos de $taxonID  
 push(@lineage,$taxonID);  
 $lineage_name{$taxonID} = $rank;  
 $node{$taxonID}{'r'} = $rank;  
   
 # 5.2) ahora guarda los de los taxones superiores  
 while($parentID ne $taxonID && $parentID > 1)  
 {  
    push(@lineage,$parentID);  
    $parentID = $node{$parentID}{'p'};  
 }  
 @sorted_lineage = sort{$a<=>$b}(@lineage);  
 $taxon = shift(@sorted_lineage);   
   
 ## 6) recupera los nombres del linaje de $taxonID leyendo NAMES de nuevo,  
 ## que contiene los taxones ordenados de menor a mayor  
 open(NAMES,$NAMESFILE) || die "# $0 : cannot open $NAMESFILE\n";  
 while(<NAMES>)  
 {  
    next if(!/scientific name/);  
    if(/^(\d+)\s+\|\s+(.*?)\|/)  
    {  
       ($ID,$name) = ($1,$2);   
       next if($ID ne $taxon);  
         
       $name =~ s/^\s+//g;   
       $name =~ s/\s+$//g;   
       $lineage_name{$ID} = $name;  
       if(@sorted_lineage){ $taxon = shift(@sorted_lineage) }  
       else{ last } # termina si no quedan mas IDs  
    }        
 }  
 close(NAMES);  
   
 ## 7) enumera el linaje de $taxoID  
 foreach $ID (@lineage)  
 {  
    $rank = $node{$ID}{'r'};  
    if($rank eq 'no'){ $rank = 'no_rank' }  
      
    $lineage_names .= "$lineage_name{$ID}, ";  
    $lineage_ranks .= "$rank, ";  
 }  
   
 print "\n# lineage : $lineage_names\n# rank  : $lineage_ranks\n";  
   

17 de junio de 2010

Qué ha hecho la Bioinformática por nosotros?

Aunque esto quedaría mejor en el blog de mi colega José Maria, os paso este enlace en inglés que me ha llegado por la lista de correo del Protein Data Bank, donde puedes proponer y elegir la contribución más importante de la Bioinformática a la ciencia. Alguien ha propuesto ya la comparación entre el genoma humano y el del chimpancé, por si estabas pensando en esto, saludos.

Clusters de proteínas ortólogas mediante el algoritmo COGs

Tras leer el artículo que sale hoy en Nature sobre la expansión del espacio de secuencias de proteínas, que se asemeja a la expansión del Universo tal como la imaginaba Hubble, he vuelto a encontrarme con el algoritmo COGs (Clusters of Orthologous Groups), originalmente creado por Tatusov en 1997 y actualizado por David Kristensen hace unas semanas. En esencia este algoritmo permite definir grupos de secuencias (potencialmente) ortólogas entre 3 o más genomas a partir de los resultados de BLAST de todos contra todos. Para ello utiliza el concepto de los 'bidirectional best hits', que se dibuja como flechas bidireccionales en esta figura, tomada del paper de Kristensen:


El código que publico hoy permite calcular COGs a partir de un directorio con archivos FASTA con secuencias de proteínas, utilizando los binarios del algoritmo COGtriangles, que se pueden obtener de SourceForge, y los de BLAST, que podemos descargar del NCBI.

 #!/usr/bin/perl -w  

 # prog5.pl    
 # Script que ejecuta el algoritmo COGtriangle sobre los archivos FASTA contenidos  
 # en el directorio -d, basado en el código original de David Kristensen (Jun 2010).  
 # El programa asume que cada archivo .faa contiene CDS de genomas distintos   
 # y puede agrupar la misma secuencia en mas de un cluster, cuando sea multidominio.  
   
 use strict 'subs';  
 use Getopt::Std;  
 use File::Basename;  
   
 ## 0) global variables, including binaries to be installed   
 ##  and parameters that affect the whole algorithm  
 # URL: ftp://ftp.ncbi.nih.gov/blast/executables/  
 my $BLASTPATH  = '/home/whatever/blast-2.2.18/';  
 my $FORMATDBEXE = $BLASTPATH . 'bin/formatdb';  
 my $BLASTPGPEXE = $BLASTPATH . 'bin/blastpgp -I T -m 9 -b 1000 -v 1000 -z 100000000';  
 # URL: http://sourceforge.net/projects/cogtriangles/files/  
 my $COGPATH = '/home/soft/COGsoft/';  
 my $MAKEHASHEXE = $COGPATH . "COGmakehash/COGmakehash -s=',' -n=1";  
 my $READBLASTEXE= $COGPATH . 'COGreadblast/COGreadblast -e=10 -q=2 -t=2';  
 my $LSEEXE   = $COGPATH . 'COGlse/COGlse';  
 my $COGTRIANGLESEXE=   
    $COGPATH . "COGtriangles/COGtriangles -t=0.5 -e=10 -n='cluster' -s=1";  
 # the default COGtriangle algorithm requires two BLAST searches  
 my $TWOBLASTRUNS=1; # set to 0 to perform only a filtered BLAST search  
 # extension of valid files in -d directories  
 my $FAAEXT   = '.faa';   
   
   
 ## 1) process command-line arguments ##############################  
 my ($INP_FASTAdir,$INP_skipBLAST,$INP_BLASToptions,$newDIR,$id) = ('',0,'');  
 my ($n_of_sequences,$pwd,$genome,$clusterid,%sequences,%genomeused,%COGs) = (0);  
 my ($allfaafile,$p2ofilename,$lsefilename,$lseoutfilename,$coglogfilename) =   
    ('all.faa','all.p2o.csv','all.lsejob.csv','all.lse.csv','all.cog.clusters.log');  
 my ($cogedgesfilename,$edgesfilename) = ('cog-edges.txt','all-edges.txt');  
   
 getopts('hsb:d:', \%opts);  
 if(($opts{'h'})||(scalar(keys(%opts))==0))   
 {   
    print "usage: $0 [options]\n";  
    print " -h this message\n";  
    print " -d input directory with FASTA .faa files (required, example -d genomes)\n";  
    print " -s skip BLAST and re-use previous searches (optional)\n";  
    die  " -b extra blastpgp options (optional, example -b '-a 2' to use 2 CPUs)\n";     
 }  
   
 if(!defined($opts{'d'})   
    || !-d $opts{'d'}){ die "# $0 : need a valid FASTA directory, exit\n"; }  
 else  
 {   
    $INP_FASTAdir = $opts{'d'};   
    if(substr($INP_FASTAdir,length($INP_FASTAdir)-1,1) eq '/'){ chop $INP_FASTAdir }  
    $pwd = `pwd`; chomp $pwd; $pwd .= '/';  
     $newDIR = $pwd.basename($INP_FASTAdir)."_COGs";  
    mkdir($newDIR) if(!-d $newDIR);  
 }  
   
 if(defined($opts{'s'})){ $INP_skipBLAST = 1 }  
 if(defined($opts{'b'}) && !$INP_skipBLAST){ $INP_BLASToptions = $opts{'b'} }  
   
 print "# results_directory=$newDIR\n\n";  
   
   
 ## 2) concatenate $FAAEXT files and create csv file with protein2organism indexing   
 opendir(FAADIR,$INP_FASTAdir) || die "# $0 : cannot list $INP_FASTAdir, exit\n";  
 @faafiles = grep {/$FAAEXT/} readdir(FAADIR);  
 close(FAADIR);  
 die "# $0 : need at least two $FAAEXT files in $INP_FASTAdir\n"   
     if(scalar(@faafiles)<2);   
   
 open(ALLFAA,">$newDIR/$allfaafile")   
     || die "# $0 : cannot create $newDIR/$allfaafile\n";  
 open(PROTORG,">$newDIR/$p2ofilename")   
     || die "# $0 : cannot create $newDIR/$p2ofilename, exit\n";  
 foreach my $faafile (@faafiles)  
 {  
    print "# reading $INP_FASTAdir/$faafile\n";  
      
    my $rhash_FASTA = read_FASTA_sequence("$INP_FASTAdir/$faafile");  
      
    foreach my $seq (sort {$a<=>$b} (keys(%$rhash_FASTA)))  
   {  
      $n_of_sequences++;  
         
       print PROTORG "$n_of_sequences,$faafile\n"; # csv file  
       #concatenated FASTA with numbers as headers  
       print ALLFAA ">$n_of_sequences\n$rhash_FASTA->{$seq}{'SEQ'}\n";   
         
       #store number - real header equivalence, could be done with BerkeleyDB   
      $sequence_data{$n_of_sequences} = $rhash_FASTA->{$seq}{'NAME'};  
     $sequence_data{$n_of_sequences.'PROT'} = $rhash_FASTA->{$seq}{'SEQ'};  
   }  
      
    $genomeused{$faafile} = 1;  
 }  
 close(PROTORG);  
 close(ALLFAA);  
   
   
 ## 3) run BLASTs searches #########################################  
 if(!$INP_skipBLAST)  
 {  
    print "# Formatting BLAST database...\n";  
    system("$FORMATDBEXE -i $newDIR/$allfaafile -o T");  
      
    if(-s 'formatdb.log'){ system("mv -f formatdb.log $newDIR") }  
   
    if($TWOBLASTRUNS)  
    {  
       print "# Running unfiltered BLAST...\n";  
       mkdir($newDIR.'/BLASTno');  
       system("$BLASTPGPEXE -d $newDIR/$allfaafile -i $newDIR/$allfaafile -F F -t F ".  
          "-o $newDIR/BLASTno/all.tab $INP_BLASToptions 2> " .  
           "$newDIR/BLASTno/blastlog_unfiltered");  
    }  
      
    print "# Running filtered BLAST...\n"; # see PMID: 20439257  
    mkdir($newDIR.'/BLASTff');  
    system("$BLASTPGPEXE -d $newDIR/$allfaafile -i $newDIR/$allfaafile -F T -t T ".  
          "-o $newDIR/BLASTff/all.tab $INP_BLASToptions 2> " .   
             "$newDIR/BLASTff/blastlog_unfiltered");  
 }  
   
   
 ## 4) calculate COG triangles ######################################  
 print "\n# making COG hash...\n";  
 mkdir($newDIR.'/BLASTconv');  
 system("$MAKEHASHEXE -i=$newDIR/$p2ofilename -o=$newDIR/BLASTconv");  
   
 print "# reading BLAST files...\n";  
 if($TWOBLASTRUNS)  
 {  
    system("$READBLASTEXE -d=$newDIR/BLASTconv -u=$newDIR/BLASTno " .    
             " -f=$newDIR/BLASTff -s=$newDIR/BLASTno");   
 }  
 else{ system("$READBLASTEXE -d=$newDIR/BLASTconv -u=$newDIR/BLASTff ".   
             "-f=$newDIR/BLASTff -s=$newDIR/BLASTff"); }  
   
 print "# checking Lineage-specific expansions...\n";  
 open (LSEIN, ">$newDIR/$lsefilename")   
    || die "# $0 : cannot create $newDIR/$lsefilename, exit\n";  
 foreach $genome (sort(keys(%genomeused)))  
 {  
    foreach my $genome2 (sort(keys(%genomeused)))  
    {  
       next if($genome eq $genome2);  
       print LSEIN "$genome,$genome2\n";  
    }  
 }  
 close LSEIN;  
   
 mkdir($newDIR.'/tmp');  
 system("$LSEEXE -t=$newDIR/tmp -d=$newDIR/BLASTconv -j=$newDIR/$lsefilename ".  
        " -p=$newDIR/$p2ofilename -o=$newDIR/$lseoutfilename > /dev/null");  
   
 print "# making COGs...\n"; # genera all-edges.txt , cog-edges.txt  
 system("$COGTRIANGLESEXE -i=$newDIR/BLASTconv -q=$newDIR/$p2ofilename " .  
           " -l=$newDIR/$lseoutfilename -o=$newDIR/$coglogfilename");  
         
 # $COGTRIANGLESEXE puts them in cwd, Jun2010!  
 if(-e $cogedgesfilename){ system("mv -f $cogedgesfilename $newDIR") }   
 if(-e $edgesfilename){ system("mv -f $edgesfilename $newDIR") }  
   
   
 ## 5) group sequences sharing COG #################################  
 open(COGS,"$newDIR/$cogedgesfilename") ||   
    die "# $0 : cannot read $newDIR/$cogedgesfilename, the program failed\n";  
 while(<COGS>)  
 {  
    #cluster00332,912,Buch_aph_Bp.faa,405,Buch_aphid_Sg.faa  
    my @data = split(/,/,$_);  
    ($clusterid,$id,$genome) = @data[0,1,2];  
    push(@{$COGs{$clusterid}{'genomes'}},$genome)   
         if(!grep(/^$genome$/,@{$COGs{$clusterid}{'genomes'}}));  
    push(@{$COGs{$clusterid}{'ids'}},$id)   
         if(!grep(/^$id$/,@{$COGs{$clusterid}{'ids'}}));  
 }  
 close(COGS);  
   
 print "\n# cluster list:\n";  
 mkdir($newDIR.'/clusters');  
 foreach $clusterid (sort {substr($a,7)<=>substr($b,7)} (keys(%COGs)))  
 {  
    print ">$newDIR/clusters/$clusterid.faa sequences=".  
          scalar(@{$COGs{$clusterid}{'ids'}}).  
       " genomes=".scalar(@{$COGs{$clusterid}{'genomes'}})."\n";  
   
    open(COGFAA,">$newDIR/clusters/$clusterid.faa") ||   
       die "# $0 : cannot create $newDIR/cogs/$clusterid.faa, exit\n";  
    foreach $id (@{$COGs{$clusterid}{'ids'}})  
    {  
       print COGFAA ">$sequence_data{$id} ($clusterid)\n$sequence_data{$id.'PROT'}\n";  
    }  
    close(COGFAA);  
 }  
   
 print "\n# total COGs = ".scalar(keys(%COGs))." in folder $newDIR/clusters\n";  
   
 exit(0);  
   
 ################################################################  
 sub read_FASTA_sequence  
 {  
    my ($infile) = @_;  
    my ($n_of_sequences,%FASTA) = (0);  
      
   open(FASTA,$infile) || die "# read_FASTA_sequence: cannot read $infile $!:\n";  
   while(<FASTA>)  
   {  
      if(/^\>(.*?)\n/)  
     {  
       $n_of_sequences++;  
       $FASTA{$n_of_sequences}{'NAME'} = $1;  
       }  
     else  
     {  
        $FASTA{$n_of_sequences}{'SEQ'} .= $_;  
       $FASTA{$n_of_sequences}{'SEQ'} =~ s/[\s|\n|\d]//g;  
       }  
    }     
   close(FASTA);  
          
    return(\%FASTA);  
 }  
   

15 de junio de 2010

Algunos comandos de R útiles en ciencia e investigación

Inspirado en:

http://www.personality-project.net/r/r.commands.html

http://www.statmethods.net/graphs/scatterplot.html

http://www.ats.ucla.edu/stat/R/notes/


Básicos
  • Ver el directorio de trabajo:
getwd()
  • Cambiar el directorio de trabajo:
setwd("path")
  • Salir de R:
q()
  • Obtener ayuda de un comando (las comillas son importantes):
help("command")
?"command"
  • Ver los objetos y variables del espacio de trabajo:
ls()
  • Borrar un objeto del espacio de trabajo:
rm(x)
rm(list=ls()) Borrar todos los objetos
  • Guardar el espacio de trabajo:
save.image() # en el archivo .RData en el directorio de trabajo
save(object list,file="myfile.RData") # los objetos deseados en el archivo elegido
  • Cargar un espacio de trabajo:
load("myfile.RData")
  • Salir de R:
q()

Vectores y matrices
  • Crear un vector:
x=c(1,2,4,8,16)
y=c(1:10)
z=c(rnorm(n))
  • Operaciones con vectores:
x=c(x)+n # suma 'n' a cada elemento
z=c(x,y) # combina 2 vectores creando un vector lineal
z=cbind(x,y) # combina 2 vectores creando una matriz de 2 columnas
z=rbind(x,y) # combina 2 vectores creando una matriz de 2 filas
replace(x,x==0,NA) # sustituye los ceros por NA
  • Operaciones con matrices:
mat[4,2] # muestra la 4ª fila y la 2ª columna
mat[3,] # muestra la 3ª fila
mat[,2] # muestra la 2ª columna
mat[,-3] # borra la 3ª columna
mat[-2,] # borra la 2ª fila
mat[1:3,3:5] # muestra las filas 1 a 3 y las columnas 3 a 5

Frames
  • Crear un frame a partir de vectores (cada vector una columna del frame):
data.fr=data.frame(x1,x2,x3 …)
  • Crear un frame a partir de una matriz:
as.data.frame(mat)
  • Conocer si un objeto es un frame:
is.data.frame(mat)
  • Convertir un frame en matriz:
as.matrix(data.frame)
  • Leer un fichero de datos separados por tabuladores con los nombres de sus columnas (1ª línea) y guardarlo en un frame:
data.fr<-read.table("ruta fichero",header=T,sep="\t")
  • Obtener los nombres de las columnas de un frame:
names(data.fr)
  • Obtener los nombres de las filas de un frame:
row.names(data.fr)
  • Obtener el número de filas de un frame:
nrow(data.fr)
  • Ver las primeras filas del frame:
head(data.fr, n=10) # las 10 primeras líneas
  • Crear vectores con el nombre de cada columna del frame (y sus datos)
attach(data.fr)
detach(data.fr) # borrar los vectores
  • Añadir una fila a un frame:
data.fr <- rbind(data.fr,data.frame(colA=1,colB="abc",colC=rnorm(1)))
  • Añadir una columna a un frame:
data.fr$colC <- data.fr$colA + 5 * data.fr$colB
  • Filtrar un frame para obtener un subconjunto de datos y guardarlo en otro frame:
subset.frame<-subset(data.fr,colA>=5 & !is.na(colB) | ColC='V')
subset.frame<-subset(data.fr,complete.cases(data.fr)) # Obtener únicamente las filas con datos en todas sus columnas
  • Ordenar un frame:
data.fr[order(data.fr$colB),] # Ordena el frame con los valores de O la columna B
data.fr[rev(order(data.fr$colB)),] # Orden inverso

Estadística
  • Calcular varios parámetros estadísticos de un conjunto de datos:
max(x)
min(x)
mean(x)
median(x)
sum(x)
var(x) # produces the variance covariance matrix
sd(x) # standard deviation
mad(x) # median absolute deviation
fivenum(x) # Tukey fivenumbers min, lowerhinge, median, upper hinge, max
Table(x) # Matriz de frecuencias
scale(x,scale=T) # centers around the mean and scales by the sd
cumsum(x) # cumulative sum
cumprod(x)
cummax(x)
cummin(x)
rev(x) # reverse the order of values in x
  • Matriz de correlación:
cor(x,y,use="pair") #correlation matrix for pairwise complete data, use="complete" for complete cases
  • Test de correlación:
cor.test(x,y,method=c('pearson'))
  • ANOVA (Análisis de la varianza):
aov.1 <- aov(colA~colB,data.fr) # one way analysis of variance (colA contains values and colB contains classes)
aov.2 = aov(colA~colB*colC,data.fr) #do a two way analysis of variance
summary(aov.1) #show the summary table
print(model.tables(aov.1,"means"),digits=3) #report the means and the number of values/class
boxplot(colA~colB,data.fr) #graphical summary appears in graphics window
  • Regresión lineal:
fit<-lm(colB~colA,data.fr) #basic linear model where x and y can be matrices (see plot.lm for plotting options)
summary(fit)
plot(data.fr$colA,data.fr$colB)
abline(fit)
  • Student's t-Test:
t.test(x,g)
pairwise.t.test(x,g)
power.anova.test(groups = NULL, n = NULL, between.var = NULL,
within.var = NULL, sig.level = 0.05, power = NULL)
power.t.test(n = NULL, delta = NULL, sd = 1, sig.level = 0.05,
power = NULL, type = c("two.sample", "one.sample", "paired"),
alternative = c("two.sided", "one.sided"),strict = FALSE)

Gráficas
  • Lista de colores disponibles en R:
colors()
  • Parámetros gráficos:
help(par)
  • Gráfico sencillo:
plot(x,y,type="p") # types: “p”: points, “l”: line, …
plot(x,y,col="red",lwd=2,type="l")
  • Dibujar un punto:
points(2,5,pch=16,col="blue",cex=3) # Dibuja el punto (2,5) en azul y con un tamaño relativo de 3
  • Etiquetar un punto:
text(2,5,label="Punto",pos=4,offset=-0.5,font=3,cex=0.75)
  • Gráfico de puntos:
plot(data.fr$colA, data.fr$colB,
main="Column A vs. Column B", xlab="Column A", ylab="Column B",
cex.main=2, cex.lab=1.5, pch=1)
  • Superponer gráfica:
lines(1-spec, sens, type='b', col=39, pch=7, lty=2)
plot(data.fr$colA, data.fr$colB,
main="Column A vs. Column C",
cex.main=2, cex.lab=1.5, pch=1, add=TRUE)
  • Ejemplo de gráfica pequeña dentro de otra mayor:
year <- 1900:2000
dollars <- (year-1899)^2
plot.within.aplot <- function()
{
    par(pin=c(1.5,1.5)) ### set the plot region size in inches
    par(mai=c(2.8,1.2,1,2.6)) ### set the 4 margin sizes in inches
    par(ps=6) ### set the font size to 6 point
    plot(year,dollars,col="blue",type="l",xlab="",ylab="") ### no axis labels
    par(new=T) ### the next plot will plot over the previous one
    par(ps=12) ### set the font size to 12 point
    par(pin=c(4.14,3.57)) ### set the plot region size back to the default
    par(mai=c(.956,.769,.769,.394)) ### set the margins back to the default
    plot(year,dollars,col="green",type="l") ### plot
}
plot.within.aplot()

Salida de datos
  • Opciones de ventanas gráficas:
X11() # abrir ventana en Linux
windows() # abrir ventana en Windows
dev.list() # mostrar ventanas abiertas
dev.cur() # mostrar ventana actual de trabajo
dev.off() # cerrar ventana actual de trabajo
dev.set(3) # seleccionar la ventana 3 como ventana de trabajo
dev.off(3) # cerrar la ventana 3
graphics.off() # cerrar todas las ventanas
  • Abrir fichero PDF para salida de datos:
pdf(file=”outfile.pdf”)

13 de junio de 2010

Tutorial para escribir trabajos académicos y tesis doctorales

A continuación se describirán técnicas útiles y recomendadas para escribir trabajos académicos y tesis doctorales.

1. Aprender a usar un buen editor de textos 

Antes de empezar a escribir hay que elegir un buen editor de textos. Normalmente la universidad posee licencia para usar Microsoft© Word, si no, en internet podemos descargar OpenOffice Writer que es gratuito y muy similar.

El siguiente paso es aprender a usarlo y aprovechar todas las funcionalidades que ofrece, para ello es muy recomendable perder tiempo en leer un buen tutorial puesto que más tarde ganaremos con creces ese tiempo.


2. Organizar la estructura del documento

Para establecer las secciones que va a contener el documento es recomendable leer y revisar otros documentos similares y adoptar su estructura o adaptarla a nuestras necesidades.
En el caso de un trabajo académico una estructura posible sería la siguiente:
  1. Índice
  2. Introducción y antecedentes
  3. Objetivos
  4. Materiales, métodos y resultados
  5. Conclusiones
  6. Bibliografía
  7. Anexos
Se pueden consultar ejemplos de trabajos académicos en diversos sitios de internet: Rincón del Vago, Monografías ...
 
Para una tesis doctoral la estructura puede ser un poco más compleja:
  1. Abreviaturas
  2. Índice
  3. Antecedentes y objetivos
  4. Introducción
  5. Materiales
  6. Métodos
  7. Resultados
  8. Discusión
  9. Conclusiones
  10. Bibliografía
  11. Anexos
Existen páginas web que recogen tesis doctorales de diferentes universidades, por ejemplo: Tesis Doctorales en Red, Teseo, Biblioteca Virtual Miguel de Cervantes ...


3. Introducir el diseño del documento en el editor de textos

Una vez tengamos claro el diseño de nuestro documento y sus secciones, introduciremos todos estos datos en el editor de textos elegido.
  • Definiremos el tamaño, orientación y márgenes del documento, incluyendo los márgenes necesarios para encuadernarlo posteriormente.
  • Daremos formato al encabezado y pie de página, incluyendo el título de las secciones del documento y los números de página.
  • Fijaremos los estilos-formatos de los párrafos, los títulos de sección, las subsecciones, tablas, figuras y otros elementos del documento, así luego todo el documento tendrá una presentación uniforme. Esto supone definir el tipo de letra, tamaño, alineación, tabulaciones, interlineado... para cada uno de los elementos nombrados.
  • Definir el estilo y numeración de títulos de tablas y figuras que se van a insertar en el documento. Se puede especificar qué tipo de título se utilizará automáticamente al insertar una imagen o una tabla y que éstos se autonumeren para no tener que modificar su numeración si se inserta una nueva imagen o tabla entre dos ya existentes.
  • Es recomendable escribir los títulos de las secciones e insertar algún contenido (texto, tablas e imágenes) y aplicarles el formato adecuado para ir viendo como quedará el documento.
  • Una vez insertados los títulos de las secciones y de algunas subsecciones de prueba se puede crear el Índice en la sección correspondiente del documente y fijar el estilo del mismo. Este índice se podrá actualizar automáticamente cada vez que se realicen modificaciones del documento.

4. Elegir y usar un gestor de bibliografía

El gestor de bibliografía es un programa de ordenador que nos ayudará a buscar, introducir, ordenar y guardar nuestras referencias bibliográficas. Además los gestores modernos incorporan la capacidad de insertar y dar formato automáticamente a la bibliografía para introducirla en nuestros documentos.
Actualmente existen varios gestores de pago: EndNote, ProCite, Reference Manager ...
Aunque también existen alternativas gratuitas: Scholar's Aid, Bibus ...
También existe Zotero que es una extensión del navegador Firefox para administrar bibliografía desde el mismo o CiteULike que es un gestor online de bibliografía, ambos son gratuitos.
Con estos programas podremos introducir de una manera rápida y sencillas las citas bibliográficas deseadas en nuestro documento de Microsoft© Word u OpenOffice Word, para más información de cómo hacerlo consultar sus manuales de uso.
 

5. Comenzar a escribir

Una vez tenemos todo preparado para comenzar a escribir. Es recomendable comenzar a escribir las secciones de las que más información tengamos recopilada y ordenada, cómo pueden ser 'Antecedentes y objetivos', 'Métodos' y 'Resultados', a su vez las secciones de 'Materiales', 'Bibliografía', 'Abreviaturas' y 'Anexos' se pueden ir completando según aparezcan sus contenidos al escribir los 'Antecedentes y objetivos', 'Métodos' y 'Resultados'.
Una vez completados los apartados anteriores y con todas las ideas expuestas y organizadas se escribirán los apartados de 'Discusión de los resultados' y 'Conclusiones'.
Es recomendable dejar para el final la 'Introducción', puesto que esta sección es de longitud muy variable y así la podemos adaptar al tiempo que nos quede tras completar el resto.
Durante el proceso es recomendable ir actualizando automáticamente el Índice para poder ver en pocas líneas el progreso de la escritura.
Por último queda dar el formato deseado a la Bibliografía, lo cual lo realiza automáticamente el programa gestor de la misma.
 

6. Diseñar una portada

La portada de nuestro trabajo será la que dé una primera impresión del mismo, por ello ha de ser acorde o incluso mejor que los contenidos.
Es aconsejable no usar únicamente texto para la misma, introducir imágenes que describan el contenido del trabajo en una buena composición gráfica ayudará a dar buena presencia a los contenidos. Para realizar las composiciones gráficas se pueden usar editores de imágenes como Photoshop, Paint Shop Pro o Gimp (éste último es gratuito) o incluso con Microsoft© Powerpoint.
Se deberán incluir en la portada: el título del trabajo, la institución a la que se pertenece (universidad, facultad, laboratorio), el nombre y apellidos del autor y del director o tutor del trabajo, la fecha y el motivo del trabajo. Los logos de la institución también se pueden incluir.
 

7. Otros 

En las tesis doctorales o trabajos que han significado gran exfuerzo y trabajo durante un largo período de tiempo se suelen incluir agradecimientos personales o un 'Prólogo' antes del contenido científico del trabajo.
También se incluye una página firmada por los directores del trabajo certificando la autenticidad y valía del mismo y se enuncian las becas o proyectos que han financiado el mismo.
 

8. Comprobación final

Tras concluir el documento, es aconsejable, si no necesario, releer varias veces el mismo entre varias personas para buscar erratas, errores ortográficos y gramaticales, u otros fallos que se pudieran haber cometido (sobretodo si se ha copiado texto de otras fuentes).
Revisar que los cambios de página no alteran las diversas secciones del documento, es aconsejable que las secciones comienzen en páginas impares para que aparezcan en hoja nueva a la derecha. Comprobar que los gráficos y tablas están correctamente posicionados y que todo tiene los formatos y estilos deseados.
Si el documento ha de ser revisado por terceras personas, esta comprobación final se puede dejar para después de las correciones.
 

9. Imprimir 

Una vez comprobado que está todo en orden llega la tan ansiada hora de imprimir el documento. Es aconsejable imprimirlo a doble cara (por motivos ecológicos) y en una impresora láser (una resolución de 300x300 puede ser más que adecuada) si el documento es en blanco y negro. Si el documento consta de páginas a color, estas pueden ser extraídas e impresas a parte en una impresora láser especial o en una de inyección de tinta. Tener en cuenta el establecer los márgenes apropiados para poder encuadernar porteriormente el documento.