Valid XHTML     Valid CSS2    

 

Programmer en R

Session de formation, décembre 2013

gilles.hunault "at" univ-angers.fr

                    

 

Solutions pour la séance numéro 3 (énoncés)

  1. La fonction read.table() contient de nombreux paramètres qui couvrent la plupart des cas classiques. En particulier pour les noms de colonne en ligne 1, il y a header=TRUE. Et pour les noms de ligne, on utilise row.names(). Enfin, avec encoding="latin1" on peut lire les caractères accentués. Avec un peu d'habitude, on finit par savoir s'en servir :

    
              
              read.table() usage:     
              -------------------     
              
              read.table(file, header = FALSE, sep = "", quote = "\"'",     
                 dec = ".", row.names, col.names,     
                 as.is = !stringsAsFactors,     
                 na.strings = "NA", colClasses = NA, nrows = -1,     
                 skip = 0, check.names = TRUE, fill = !blank.lines.skip,     
                 strip.white = FALSE, blank.lines.skip = TRUE,     
                 comment.char = "#",     
                 allowEscapes = FALSE, flush = FALSE,     
                 stringsAsFactors = default.stringsAsFactors(),     
                 fileEncoding = "", encoding = "unknown", text)     
              
              
    

    Pour retirer la dernière ligne, une fois les données lues, on utilise l'index négatif de cette ligne. La fonction row.names() prend un vecteur de noms uniques pour en faire des noms de lignes. Les constructions classiques de noms de ligne utilisent donc paste(), substr() et sprintf().

    
          # si la ligne 1 contient le nom des lignes, la lecture simple ne suffit pas     
              
          cats("une lecture ratée")     
          data <- read.table("derniere.txt")     
              
          print(data)     
              
          # donc il faut ajouter header=TRUE     
              
          cats("une lecture réussie")     
          data <- read.table("derniere.txt",header=TRUE,row.names=1,encoding="latin1")     
          data <- data[ -nrow(data), ]     
              
          print(data)     
              
          # normalisation des noms de ligne     
              
          cats("aménagement des noms de ligne (1)")     
          row.names(data) <- paste("Lig_",sprintf("%03d",as.numeric(row.names(data))),sep="")     
              
          print(data)     
              
          # une autre définition des noms de ligne     
              
          cats("aménagement des noms de ligne (2)")     
          debutGenre      <- substr(data[,"genre"],1,3)     
          debutEspece     <- substr(data[,"espèce"],1,3)     
          row.names(data) <- paste(debutGenre,"_",debutEspece,"_", sprintf("%03d",1:nrow(data)),sep="")     
              
          print(data)     
              
              
    
    
              
         une lecture ratée     
         =================     
              
              V1        V2     V3            V4   V5  V6         V7        V8         V9        V10         V11         V12     
         1   num accession length         reign pfam cdd  foldindex        pi         mw      gravy       genre   esp\xe8ce     
         2    35  ABS44867    200 Viridiplantae  N/A N/A -0.0835869 6.1399999 20295.8008 -1.0180905       Oryza      sativa     
         3   822 A2211386C    153 Viridiplantae  N/A N/A -0.1659534 9.3100004 15909.3203 -1.2745098 Pseudotsuga   menziesii     
         4   964  ABB55135    132 Viridiplantae  N/A N/A -0.2853720 9.4399996 14103.7598 -1.5803030       Pinus yunnanensis     
         5   965  AAW59164    143 Viridiplantae  N/A N/A -0.1855139 8.6999998 15209.6104 -1.3573427       Pinus       taeda     
         6   966  AAW59168    144 Viridiplantae  N/A N/A -0.2060405 9.3100004 15422.8604 -1.4013889       Pinus       taeda     
         7   980  AAW59174    143 Viridiplantae  N/A N/A -0.1803197 8.6999998 15237.6699 -1.3405594       Pinus       taeda     
         8   981  AAW59176    143 Viridiplantae  N/A N/A -0.2015961 9.3100004 15294.7100 -1.3867133       Pinus       taeda     
         9 total         7      7             7    0   0          7         7          7          7           7           7     
              
         une lecture réussie     
         ===================     
              
             accession length         reign pfam cdd  foldindex   pi       mw     gravy       genre      espèce     
         35   ABS44867    200 Viridiplantae  N/A N/A -0.0835869 6.14 20295.80 -1.018091       Oryza      sativa     
         822 A2211386C    153 Viridiplantae  N/A N/A -0.1659534 9.31 15909.32 -1.274510 Pseudotsuga   menziesii     
         964  ABB55135    132 Viridiplantae  N/A N/A -0.2853720 9.44 14103.76 -1.580303       Pinus yunnanensis     
         965  AAW59164    143 Viridiplantae  N/A N/A -0.1855139 8.70 15209.61 -1.357343       Pinus       taeda     
         966  AAW59168    144 Viridiplantae  N/A N/A -0.2060405 9.31 15422.86 -1.401389       Pinus       taeda     
         980  AAW59174    143 Viridiplantae  N/A N/A -0.1803197 8.70 15237.67 -1.340559       Pinus       taeda     
         981  AAW59176    143 Viridiplantae  N/A N/A -0.2015961 9.31 15294.71 -1.386713       Pinus       taeda     
              
         aménagement des noms de ligne (1)     
         =================================     
              
                 accession length         reign pfam cdd  foldindex   pi       mw     gravy       genre      espèce     
         Lig_035  ABS44867    200 Viridiplantae  N/A N/A -0.0835869 6.14 20295.80 -1.018091       Oryza      sativa     
         Lig_822 A2211386C    153 Viridiplantae  N/A N/A -0.1659534 9.31 15909.32 -1.274510 Pseudotsuga   menziesii     
         Lig_964  ABB55135    132 Viridiplantae  N/A N/A -0.2853720 9.44 14103.76 -1.580303       Pinus yunnanensis     
         Lig_965  AAW59164    143 Viridiplantae  N/A N/A -0.1855139 8.70 15209.61 -1.357343       Pinus       taeda     
         Lig_966  AAW59168    144 Viridiplantae  N/A N/A -0.2060405 9.31 15422.86 -1.401389       Pinus       taeda     
         Lig_980  AAW59174    143 Viridiplantae  N/A N/A -0.1803197 8.70 15237.67 -1.340559       Pinus       taeda     
         Lig_981  AAW59176    143 Viridiplantae  N/A N/A -0.2015961 9.31 15294.71 -1.386713       Pinus       taeda     
              
         aménagement des noms de ligne (2)     
         =================================     
              
                     accession length         reign pfam cdd  foldindex   pi       mw     gravy       genre      espèce     
         Ory_sat_001  ABS44867    200 Viridiplantae  N/A N/A -0.0835869 6.14 20295.80 -1.018091       Oryza      sativa     
         Pse_men_002 A2211386C    153 Viridiplantae  N/A N/A -0.1659534 9.31 15909.32 -1.274510 Pseudotsuga   menziesii     
         Pin_yun_003  ABB55135    132 Viridiplantae  N/A N/A -0.2853720 9.44 14103.76 -1.580303       Pinus yunnanensis     
         Pin_tae_004  AAW59164    143 Viridiplantae  N/A N/A -0.1855139 8.70 15209.61 -1.357343       Pinus       taeda     
         Pin_tae_005  AAW59168    144 Viridiplantae  N/A N/A -0.2060405 9.31 15422.86 -1.401389       Pinus       taeda     
         Pin_tae_006  AAW59174    143 Viridiplantae  N/A N/A -0.1803197 8.70 15237.67 -1.340559       Pinus       taeda     
         Pin_tae_007  AAW59176    143 Viridiplantae  N/A N/A -0.2015961 9.31 15294.71 -1.386713       Pinus       taeda     
              
    

    Pour avoir une numérotation interne au couple genre/espèce, le plus simple est de trier par couple et ensuite de numéroter dans une boucle :

    
         # tri genre espèce pour exercice 1 séance 3     
              
         data <- read.table("derniere.txt",header=TRUE,row.names=1,encoding="latin1",stringsAsFactors=FALSE)     
         data <- data[ -nrow(data), ]     
              
         dao        <- data[order(da$genre,da$espèce),]     
         dao$genre  <- reformate(dao$genre)     
         dao$espèce <- reformate(dao$espèce)     
              
         cpge <- function(x) {     
           nbe <- length(x)                # voici ce qu'il ne faut pas faire :     
           npc <- rep(1,nbe)               #   écrire une fonction sans commentaire     
           for (ide in (2:nbe)) {          #   avec des noms de variable non explicités     
             if (x[ide] ==x[ide-1]) {      #     
               npc[ide] <- npc[ide-1]+1    # bonjour la lisibilité !     
             } # fin si     
           } # fin pour     
           return(npc)     
         } # fin de fonction     
              
         debutGenre     <- substr(dao[,"genre"],1,3)     
         debutEspece    <- substr(dao[,"espèce"],1,3)     
         numge          <- cpge(paste(dao$genre,dao$espèce))     
         nomslig        <- paste(debutGenre,"_",debutEspece,"_", sprintf("%03d",numge),sep="")     
         row.names(dao) <- paste(debutGenre,"_",debutEspece,"_", sprintf("%03d",numge),sep="")     
              
         print(dao)     
              
    
    
                     accession length         reign pfam cdd  foldindex   pi       mw     gravy       genre      espèce     
         Ory_sat_001  ABS44867    200 Viridiplantae  N/A N/A -0.0835869 6.14 20295.80 -1.018091 Oryza _____ sativa ____     
         Pin_tae_001  AAW59164    143 Viridiplantae  N/A N/A -0.1855139 8.70 15209.61 -1.357343 Pinus _____ taeda _____     
         Pin_tae_002  AAW59168    144 Viridiplantae  N/A N/A -0.2060405 9.31 15422.86 -1.401389 Pinus _____ taeda _____     
         Pin_tae_003  AAW59174    143 Viridiplantae  N/A N/A -0.1803197 8.70 15237.67 -1.340559 Pinus _____ taeda _____     
         Pin_tae_004  AAW59176    143 Viridiplantae  N/A N/A -0.2015961 9.31 15294.71 -1.386713 Pinus _____ taeda _____     
         Pin_yun_001  ABB55135    132 Viridiplantae  N/A N/A -0.2853720 9.44 14103.76 -1.580303 Pinus _____ yunnanensis     
         Pse_men_001 A2211386C    153 Viridiplantae  N/A N/A -0.1659534 9.31 15909.32 -1.274510 Pseudotsuga menziesii _     
              
    

    Avec les paramètres skip, comment.char, blank.lines.skip et nrows de la fonction read.table(), lire partiellement un fichier avec des lignes vides et des commentaires est un jeu d'enfant :

    
         data <- read.table(     
            file="videcmt.txt",     
            skip=5,     
            comment.char="#",     
            blank.lines.skip=TRUE,     
            row.names=1,     
            nrows=8     
         ) # fin de read.table     
              
         colnames(data) <- c("Duree","Bolus","Serie")     
         print(data)     
              
              
    
    
             Duree Bolus Serie     
         A35   617   552     1     
         A37   417   652     1     
         A38   410   565    1A     
         A39   390   700    1A     
         A40   500   540    1A     
         A60   500   540    1B     
         A61   480   408    1B     
         A92   480   408     2     
              
    
  2. Avec les indices dans les crochets et la séquence avec le symbole deux-points, on peut afficher des parties de dataframe. Si on utilise ncol() et nrow(), on peut trouver les indices des dernières lignes et colonnes, mais les fonctions head() et tail() sont à l'usage plus pratiques. Pour transposer, il faut utiliser la fonction t().

    
         # lecture des données dans le "mauvais sens"     
              
          cats("lecture")     
          data <- read.table("transp.txt",header=TRUE,row.names=1)     
          print(data)     
              
         # transposition     
              
          cats(" on transpose")     
          data <- t(data)     
          print(data)     
              
         # premières/dernières lignes/colonnes     
              
         cats("affichages")     
         nbLig  <- nrow(data)     
         nbCol  <- ncol(data)     
         colnames(data) <- paste(colnames(data),"_V",1:nbCol,sep="")     
         print( data[ (1:3), ] ) # ou head(data,n=3)     
         cat("...\n")     
         print( data[ ((nbLig-3):nbLig), (1:3)] )  # ou tail(data,n=4)     
         cat("\n")     
         print( data[ (3:5) , (1:3) ] )     
         print( data[ (5:7) , ((nbCol-2):nbCol) ] )     
              
    
    
              
         lecture     
         =======     
              
              M001 M002 M003 M004 M005 M006 M007 M008 M009 M010     
         SEXE    1    0    1    1    0    1    1    1    0    1     
         AGE    62   60   31   27   22   70   19   53   62   63     
         PROF    1    9    9    8    8    4    8    6   16   16     
         ETUD    2    3    4    4    4    1    4    2    4    0     
         REGI    2    4    4    1    1    1    4    2    2    1     
         USAG    3    1    1    1    2    1    2    3    2    0     
              
          on transpose     
         =============     
              
              SEXE AGE PROF ETUD REGI USAG     
         M001    1  62    1    2    2    3     
         M002    0  60    9    3    4    1     
         M003    1  31    9    4    4    1     
         M004    1  27    8    4    1    1     
         M005    0  22    8    4    1    2     
         M006    1  70    4    1    1    1     
         M007    1  19    8    4    4    2     
         M008    1  53    6    2    2    3     
         M009    0  62   16    4    2    2     
         M010    1  63   16    0    1    0     
              
         affichages     
         ==========     
              
              SEXE_V1 AGE_V2 PROF_V3 ETUD_V4 REGI_V5 USAG_V6     
         M001       1     62       1       2       2       3     
         M002       0     60       9       3       4       1     
         M003       1     31       9       4       4       1     
         ...     
              SEXE_V1 AGE_V2 PROF_V3     
         M007       1     19       8     
         M008       1     53       6     
         M009       0     62      16     
         M010       1     63      16     
              
              SEXE_V1 AGE_V2 PROF_V3     
         M003       1     31       9     
         M004       1     27       8     
         M005       0     22       8     
              ETUD_V4 REGI_V5 USAG_V6     
         M005       4       1       2     
         M006       1       1       1     
         M007       4       4       2     
              
    

    Pour filtrer des noms de ligne, la fonction regexpr() est tout-à-fait adaptée :

    
         cats("toutes les données")     
         data <- read.table("pas_2_3.txt",head=TRUE,row.names=1)     
         print(data)     
              
         cats("filtrage")     
         flt  <- regexpr("_[23]$",row.names(data))>0     
         print(data[ !flt ,])     
              
    
    
              
         toutes les données     
         ==================     
              
               Duree Bolus Serie     
         A35     617   552     1     
         A37     417   652     1     
         A38_1   410   565    1A     
         A39     390   700    1A     
         A40_2   500   540    1A     
         A60_2   500   540    1B     
         A61     480   408    1B     
         A92_3   480   408     2     
              
         filtrage     
         ========     
              
               Duree Bolus Serie     
         A35     617   552     1     
         A37     417   652     1     
         A38_1   410   565    1A     
         A39     390   700    1A     
         A61     480   408    1B     
              
    

    Pour des affichages sélectifs de lignes, les conditions logiques avec & et | suffisent souvent :

    
          elf <- lit.dar.wd("elf.dar")     
              
          cats("femmes de moins de 30 ans (début)")     
          flt <- (elf$SEXE==1) & (elf$AGE<30)     
          head( elf[ flt , c("SEXE","AGE") ] )     
              
          cats("hommes ou personnes de plus de 60 ans (début)")     
          flt <- (elf$SEXE==0) | (elf$AGE>60)     
          head( elf[ flt , c("SEXE","AGE") ] )     
              
    
    
              
         femmes de moins de 30 ans (début)     
         =================================     
              
              SEXE AGE     
         M004    1  27     
         M007    1  19     
         M012    1  11     
         M019    1  21     
         M020    1  23     
         M025    1  14     
              
         hommes ou personnes de plus de 60 ans (début)     
         =============================================     
              
              SEXE AGE     
         M001    1  62     
         M002    0  60     
         M005    0  22     
         M006    1  70     
         M009    0  62     
         M010    1  63     
              
    

    Pour accéder à une colonne d'un dataframe, on peut utiliser son nom avec $, son numéro de colonne ou son nom comme indice. Il est conseillé d'utiliser le nom de colonne plutôt que le numéro parce que c'est plus sûr. Pour supprimer, on peut utiliser l'indice négatif mais la notation en liste avec dollar et NULL est plus concise.

    
          elf <- lit.dar.wd("elf.dar")     
          mini <- head(elf)     
              
          cats("trois moyens d'accéder à la colonne AGE")     
          v1 <-  mini[ ,2 ]     
          v2 <-  mini[ ,"AGE" ]     
          v3 <-  mini$AGE     
          print( cbind( v1, v2, v3 ) )     
              
          cats("ce sont bien les mêmes structures :")     
          cat(" v1=v2 ? ",identical(v1,v2),"\n")     
          cat(" v1=v3 ? ",identical(v1,v3),"\n")     
          cat(" v2=v2 ? ",identical(v2,v3),"\n")     
              
          cats("supprimons les lignes 3 à 5")     
          mini2 <- mini[ -(3:5), ]     
          print(mini2)     
              
          # pour supprimer la colonne AGE :     
              
            # solution 1     
              
            mini <- mini[, -2]     
              
            # solution 2     
              
            mini <- mini[, -which("AGE"==names(mini)) ]     
              
            # solution 3     
              
            mini$AGE <- NULL     
              
              
    
    
              
         trois moyens d'accéder à la colonne AGE     
         =======================================     
              
              v1 v2 v3     
         [1,] 62 62 62     
         [2,] 60 60 60     
         [3,] 31 31 31     
         [4,] 27 27 27     
         [5,] 22 22 22     
         [6,] 70 70 70     
              
         ce sont bien les mêmes structures :     
         ===================================     
              
          v1=v2 ?  TRUE     
          v1=v3 ?  TRUE     
          v2=v2 ?  TRUE     
              
         supprimons les lignes 3 à 5     
         ===========================     
              
              SEXE AGE PROF ETUD REGI USAG     
         M001    1  62    1    2    2    3     
         M002    0  60    9    3    4    1     
         M006    1  70    4    1    1    1     
              
    

    Pour renommer occasionnellement une colonne, on peut utiliser son numéro et modifier le colnames() de la structure. Pour du renommage "massif", il vaut mieux passer par la fonction rename.pattern() du package epicalc.

    
              
         > # les données     
         >     
         > elf <- lit.dar.wd("elf.dar")     
              
         > mini <- head(elf)     
              
         > print( mini )     
              SEXE AGE PROF ETUD REGI USAG     
         M001    1  62    1    2    2    3     
         M002    0  60    9    3    4    1     
         M003    1  31    9    4    4    1     
         M004    1  27    8    4    1    1     
         M005    0  22    8    4    1    2     
         M006    1  70    4    1    1    1     
              
         > # on veut renommer la colonne "PROF" en "csp"     
         > # solution (1) : on connait le numéro     
         >     
         > print(cbind(colnames(mini)))     
              [,1]     
         [1,] "SEXE"     
         [2,] "AGE"     
         [3,] "PROF"     
         [4,] "ETUD"     
         [5,] "REGI"     
         [6,] "USAG"     
              
         > colnames(mini)[3] <- "csp"     
              
         > print( mini )     
              SEXE AGE csp ETUD REGI USAG     
         M001    1  62   1    2    2    3     
         M002    0  60   9    3    4    1     
         M003    1  31   9    4    4    1     
         M004    1  27   8    4    1    1     
         M005    0  22   8    4    1    2     
         M006    1  70   4    1    1    1     
              
         > # on veut renommer la colonne "csp" en "prof"     
         > # solution (2) : on ne connait pas le numéro     
         >     
         > avant <- "csp"     
              
         > apres <- "prof"     
              
         > noms  <- colnames(mini)     
              
         > colnames(mini)[ which(noms==avant) ] <- apres     
              
         > print( mini )     
              SEXE AGE prof ETUD REGI USAG     
         M001    1  62    1    2    2    3     
         M002    0  60    9    3    4    1     
         M003    1  31    9    4    4    1     
         M004    1  27    8    4    1    1     
         M005    0  22    8    4    1    2     
         M006    1  70    4    1    1    1     
              
         > # on veut renommer la colonne "prof" en "csp"     
         > # solution (3) : rename de epicalc     
         >     
         > library(epicalc)     
              
         Loading required package: foreign     
         Loading required package: survival     
         Loading required package: splines     
         Loading required package: MASS     
         Loading required package: nnet     
              
         > rename.pattern(x1="prof",x2="csp",dataFrame=mini)     
         Note the following change(s) in variable name(s):     
              Old var names   New var names     
              "prof"          "csp"     
              
         > print( mini )     
              SEXE AGE csp ETUD REGI USAG     
         M001    1  62   1    2    2    3     
         M002    0  60   9    3    4    1     
         M003    1  31   9    4    4    1     
         M004    1  27   8    4    1    1     
         M005    0  22   8    4    1    2     
         M006    1  70   4    1    1    1     
              
    
  3. Le package XML et ses fonctions readHTMLTable() et readHTMLList() est prévu pour cela. Il faut sans doute juste utiliser des fonctions sur chaines comme iconv() et str_replace() afin d'obtenir des informations "propres".

    
         ## récupération d'un tableau XHTML dans R     
              
         # chargement du package XML     
              
         library(XML)     
              
         # chargement du package stringr     
              
         library(stringr) # pour la fonction str_replace()     
              
         # url de la page Web à utiliser     
              
         url  <- "http://forge.info.univ-angers.fr/~gh/wstat/Programmation_R/progr.php?n=1&m=s"     
         tabp <- readHTMLTable(url,which=3,stringsAsFactors=FALSE)     
         print(tabp,right=FALSE)     
              
         # un peu de "ménage"     
              
         colnames(tabp) <- str_replace(colnames(tabp),"\\n","")     
              
         # tout sauf les deux derniers caractères     
              
         tsdc <- function(x) { substr(x,1,nchar(x)-2) }     
              
         tabp[,2] <- as.numeric( tsdc(tabp[,2]) )     
         print(tabp,right=FALSE)     
              
         ## récupération d'une liste     
              
         ip  <- "http://fr.wikipedia.org/wiki/Institut_Pasteur"     
         cdr <- readHTMLList(ip,which=7)     
              
         # conversion des accents     
              
         iconv(cdr,from="UTF-8",to="LATIN1")     
         print(cbind(cdr))     
              
              
    
    
              
         > ## récupération d'un tableau XHTML dans R     
         >     
         > # chargement du package XML     
         >     
         > library(XML)     
              
         > # chargement du package stringr     
         >     
         > library(stringr) # pour la fonction str_replace()     
              
         > # url de la page Web à utiliser     
         >     
         > url  <- "http://forge.info.univ-angers.fr/~gh/wstat/Programmation_R/progr.php?n=1&m=s"     
              
         > tabp <- readHTMLTable(url,which=3,stringsAsFactors=FALSE)     
              
         > print(tabp,right=FALSE)     
           \nPackage \nNb_objets \nLien     
         1 base      1167Â       lls_base.sor     
         2 gdata     64Â         lls_gdata.sor     
         3 tools     97Â         lls_tools.sor     
         4 utils     198Â        lls_utils.sor     
              
         > # un peu de "ménage"     
         >     
         > colnames(tabp) <- str_replace(colnames(tabp),"\\n","")     
              
         > # tout sauf les deux derniers caractères     
         >     
         > tsdc <- function(x) { substr(x,1,nchar(x)-2) }     
              
         > tabp[,2] <- as.numeric( tsdc(tabp[,2]) )     
              
         > print(tabp,right=FALSE)     
           Package Nb_objets Lien     
         1 base    1167      lls_base.sor     
         2 gdata     64      lls_gdata.sor     
         3 tools     97      lls_tools.sor     
         4 utils    198      lls_utils.sor     
              
         > ## récupération d'une liste     
         >     
         > ip  <- "http://fr.wikipedia.org/wiki/Institut_Pasteur"     
              
         > cdr <- readHTMLList(ip,which=7)     
              
         > # conversion des accents     
         >     
         > iconv(cdr,from="UTF-8",to="LATIN1")     
          [1] "Biologie cellulaire et infection"              "Biologie du développement et cellules souches"     
          [3] "Biologie structurale et chimie"                "Génomes et génétique"     
          [5] "Immunologie"                                   "Infection et épidémiologie"     
          [7] "Microbiologie"                                 "Neuroscience"     
          [9] "Parasitologie et mycologie"                    "Virologie"     
              
         > print(cbind(cdr))     
               cdr     
          [1,] "Biologie cellulaire et infection"     
          [2,] "Biologie du développement et cellules souches"     
          [3,] "Biologie structurale et chimie"     
          [4,] "Génomes et génétique"     
          [5,] "Immunologie"     
          [6,] "Infection et épidémiologie"     
          [7,] "Microbiologie"     
          [8,] "Neuroscience"     
          [9,] "Parasitologie et mycologie"     
         [10,] "Virologie"     
              
    

    Si ce genre de récupération vous intéresse, il y a d'autres exemples dans notre introduction non élémentaire à R, exercice 5 du cours 2.

  4. Le code suivant est presque suffisant pour lire un entier ou des entiers au clavier :

    
         litEntier <- function() {     
              
          repeat {     
             lu     <- readline("litEntier> donner un nombre entier : ")     
             lulu   <<- lu                                                # le doublement de < n'est pas une erreur     
             try(n  <- as.integer(lu))     
             if (is.na(n)) {     
               cat("litEntier> hélas, ce n'est pas un entier !\n")     
             } else {     
                break     
             } # fin de si     
          } # fin de répéter     
              
          cat("Merci. Votre nombre est ",n," et son carré est ",n*n,"\n")     
              
          return( n)     
              
         } # fin de fonction litEntier     
              
         # ------------------------------------------------------------------------     
              
         litEntierAvecRegexpr <- function() {     
              
          nbLect <- 0     
          repeat {     
             if (nbLect==0) {     
                demande <- "litEntierAvecRegexpr> donner un nombre entier : "     
             } else {     
                demande <- "litEntierAvecRegexpr> redonner un nombre entier : "     
             } # fin si     
             lu     <- readline(demande)     
             nbLect <- nbLect + 1     
             if ((regexpr("^[0-9]+$",lu,perl=TRUE)==1)) {  # attention : "[0-9]+" n'est pas suffisant     
                break     
             } # fin de si     
             cat("litEntierAvecRegexpr> hélas, ce n'est pas un entier !\n")     
          } # fin de répéter     
              
          n <- as.numeric(lu)     
          cat("Merci. Votre nombre est ",n," et son carré est ",n*n,"\n")     
              
          return( n)     
              
         } # fin de fonction litEntierAvecRegexpr     
              
         # ------------------------------------------------------------------------     
              
         litEntiers <- function() {     
              
           repeat {     
             lus <- readline("donner des nombre entiers séparés par des espaces : ")     
             if ((regexpr("^[0-9 ]+$",lus,perl=TRUE)==1)) {     
                break     
             } # fin de si     
             cat("hélas, ce ne sont pas des entiers séparés par des espaces !\n")     
           } # fin de répéter     
              
           lulu <<-  lus               # le doublement de < n'est pas une erreur     
           ldm   <-  unlist( strsplit(x=lus,split="\\s+"))     
           vect  <-  as.vector(sapply(X=ldm,FUN=as.integer))     
              
           cat("Merci. Vous avez entré ",length(vect)," entier(s).\n")     
              
           return(vect)     
              
         } # fin de fonction litEntiers     
              
    
    
              
         démo de litEntier     
         =================     
              
         litEntier> donner un nombre entier : oui     
         litEntier> hélas, ce n'est pas un entier !     
         litEntier> donner un nombre entier : 17 25     
         litEntier> hélas, ce n'est pas un entier !     
         litEntier> donner un nombre entier : -6.1     
         Merci. Votre nombre est  -6  et son carré est  36     
              
         démo de litEntierAvecRegexpr     
         ============================     
              
         litEntierAvecRegexpr> donner un nombre entier : oui     
         litEntierAvecRegexpr> hélas, ce n'est pas un entier !     
         litEntierAvecRegexpr> redonner un nombre entier : 17 25     
         litEntierAvecRegexpr> hélas, ce n'est pas un entier !     
         litEntierAvecRegexpr> redonner un nombre entier : 6.1     
         litEntierAvecRegexpr> hélas, ce n'est pas un entier !     
         litEntierAvecRegexpr> redonner un nombre entier : -3     
         litEntierAvecRegexpr> hélas, ce n'est pas un entier !     
         litEntierAvecRegexpr> redonner un nombre entier : 3     
         Merci. Votre nombre est  3  et son carré est  9     
              
         démo de litEntiers     
         ==================     
              
         donner des nombre entiers séparés par des espaces : 5 12 17     
         Merci. Vous avez entré  3  entier(s).     
         [1] 5 12 17     
              
         Messages d'avis :     
         1: In doTryCatch(return(expr), name, parentenv, handler) :     
            NAs introduits lors de la conversion automatique     
         2: In doTryCatch(return(expr), name, parentenv, handler) :     
            NAs introduits lors de la conversion automatique     
         3: In lapply(X = X, FUN = FUN, ...) :     
            NAs introduits lors de la conversion automatique     
              
              
    

    Mais ce code n'est pas correct, ni efficace : passer par as.integer est maladroit, car pour 6.1 cela ne renvoie pas d'erreur. Et malheureusement, comme le montre l'affichage précédent, la première fonction nommée litEntier() génère des messages d'avertissement (et non pas des messages d'erreurs). Donc l'aide sur try() qui propose le paramètre silent=TRUE n'est pas adapté. Comme les "warnings" sont gérés par les options (chercher warn), le code suivant est plus "propre" :

    
         litEntier <- function() {     
              
          options(warn=-1)     
          # mieux : sovWarn <- as.integer( options("warn") )     
          # puis    options(warn=-1)     
              
          repeat {     
             lu <- readline("litEntier> donner un nombre entier : ")     
             lulu <<- lu     
             try(n <- as.integer(lu))     
             if (is.na(n)) {     
               cat("litEntier> hélas, ce n'est pas un entier !\n")     
             } else {     
                break     
             } # fin de si     
          } # fin de répéter     
              
          options(warn=0)     
          # mieux : options(warn=sovWarn)     
              
          cat("Merci. Votre nombre est ",n," et son carré est ",n*n,"\n")     
              
          return( n)     
              
         } # fin de fonction litEntier     
              
              
    

    De même, la fonction nommée litEntierAvecRegexpr() ne sait pas reconnaitre un entier signé. Rajouter juste le signe moins et donc utiliser ^[-0-9]$ ne suffit pas : +3 ne serait pas reconnu. Nous vous laissons comprendre la solution suivante.

    
         litEntierAvecRegexprEtSigne <- function() {     
              
          nbLect <- 0     
          repeat {     
             if (nbLect==0) {     
                demande <- "litEntierAvecRegexprEtSigne> donner un nombre entier : "     
             } else {     
                demande <- "litEntierAvecRegexprEtSigne> redonner un nombre entier : "     
             } # fin si     
             lu     <- readline(demande)     
             nbLect <- nbLect + 1     
             if ((regexpr("^[+-]?[0-9]+$",lu,perl=TRUE)==1)) {  # attention : "[0-9]+" n'est pas suffisant     
                break     
             } # fin de si     
             cat("litEntierAvecRegexprEtSigne> hélas, ce n'est pas un entier !\n")     
          } # fin de répéter     
              
          n <- as.numeric(lu)     
          cat("Merci. Votre nombre est ",n," et son carré est ",n*n,"\n")     
              
          return( n)     
              
         } # fin de fonction litEntierAvecRegexprEtSigne     
              
         # ------------------------------------------------------------------------     
              
    
  5. Il s'agit d'une généralisation de l'exercice précédent. Pour des nombres réels éventuellement signés, l'expression régulière est un peu plus compliquée. Pour des fractions, une fois passé le cap de la validité de l'expression, il faut convertir chaque fraction en un nombre, par exemple avec notre fonction convFrac().

    
         litNombres <- function(chaine) { library(stringr)     
              
              if (missing(chaine)) {     
                cat("paramètre manquant, la syntaxe est litNombres(chaine) \n");     
                cat("par exemple : litNombres(\"1 3 12.8 -7      3 \")\n\n")     
                return()     
              } # fin de si     
              
              if (chaine=="") {     
                return( numeric(0) )     
              } # fin de si     
              
              if (regexpr("^( *[+-]?[0-9]*(\\.|,)?[0-9]* *)*$",chaine,perl=TRUE)==1) {     
                cat("ok\n")     
                chaine <- str_replace_all(chaine,",",".")     
                vectn  <- unlist(strsplit(x=ghtrim(chaine),split="\\s+",perl=TRUE))     
                return(as.numeric(vectn))     
              } else {     
                cat("non\n")     
                return( c() )     
              } # fin si     
              
         } # fin de fonction litNombres     
              
         # ----------------------------------------     
              
         convFrac <- function(chaine) {     
              
              chaine <- ghtrim(chaine) # supprime les espaces de début et fin     
              
              if (1!=regexpr("[0-9]+/[0-9]+",chaine)) {     
                return(NA)     
              } else {     
                parts <- as.numeric(unlist(strsplit(chaine,"/")))     
                return(parts[1]/parts[2])     
              } # fin si     
              
         } # fin de fonction convFrac     
              
         # ----------------------------------------     
              
         litFractions <- function(chaine) {     
              
         vectFract <- unlist(strsplit(x=ghtrim(chaine),split=" +",perl=TRUE))     
         cat("on est passé de : ")     
         str(chaine)     
         cat("à               : ")     
         str(vectFract)     
         cat("\n")     
         return(as.vector(sapply(vectFract,convFrac)))     
              
         } # fin de fonction litFractions     
              
         # ----------------------------------------     
              
         cats("exemples d'utilisations :" )     
              
         v <- litNombres("1 3 12.8 -7      3 ")     
         print( str(v) )     
              
         fr <- "3/4"     
         cat("la fraction ",fr," vaut ",convFrac(fr),"\n")     
              
         (frs <- litFractions("   4/3   2/3           1/5") )     
              
              
              
    
    
              
         exemples d'utilisations :     
         =========================     
              
              
         > v <- litNombres("1 3 12.8 -7      3 ")     
         ok     
              
         > print( str(v) )     
          num [1:5] 1 3 12.8 -7 3     
         NULL     
              
         > w <- litNombres("1 3 12.8 -7,5      3 ")     
         ok     
              
         > print(w)     
         [1]  1.0  3.0 12.8 -7.5  3.0     
              
         > fr <- "3/4"     
              
         > cat("la fraction ",fr," vaut ",convFrac(fr),"\n")     
         la fraction  3/4  vaut  0.75     
              
         > (frs <- litFractions("   4/3   2/3           1/5") )     
         on est passé de :  chr "   4/3   2/3           1/5"     
         à               :  chr [1:3] "4/3" "2/3" "1/5"     
              
         [1] 1.3333333 0.6666667 0.2000000     
              
              
    

    Contrairement à <-, l'opérateur <<- réalise une affectation dans l'environnement global. Donc si on écrit n <- 2 dans une fonction, n est une variable locale et n'existe pas en dehors (ou, si n existait avant, elle est masquée dans la fonction par la variable n locale, mais non modifiée). Par contre, si on écrit n <<- 2 dans une fonction, n devient une variable globale et remplace éventuellement celle qui existait déjà :

    
          queVautn <- function() {     
            if (exists("n")) {     
              cat("n vaut ",n,"\n")     
            } else {     
              cat("n n'existe pas.\n")     
            } # fin si     
          } # fin de fonction queVautn     
              
          demoLocale <- function() {     
              
            n <- 3     
            cat(" dans la fonction, n vaut ",n,"\n")     
              
          } # fin de fonction demoLocale     
              
          # démonstration     
              
            n <- 1     
              
            queVautn()     
              
            demoLocale()     
              
            queVautn()     
              
            rm(n)     
              
            demoLocale()     
              
            queVautn()     
              
    
    
         n vaut  1     
         dans la fonction, n vaut  3     
         n vaut  1     
         dans la fonction, n vaut  3     
         n n'existe pas.     
              
    

    Voici une façon de s'en servir : vous êtes en train de mettre au point une fonction et vous voulez tester en ligne de commande des instructions sur des variables créées par la fonction. Utiliser <<- vous permet d'accéder à ces variables en dehors de la fonction...

  6. Notre fonction analexies() de notre fichier statgh.r fait le travail demandé en ce qui concerne les dictionnaires :

    
         # le fichier statgh.r contient la fonction analexies     
              
         source("statgh.r")     
              
              
         ## autres possibilités (changer éventuellement les chemins d'accès) :     
         #    source("/home/moi/stats/statgh.r")     
         #    source("http://forge.info.univ-angers.fr/~gh/statgh.r")     
         #    source("K:/Stat_ad/statgh.r")     
              
              
         adt <- analexies( lit.texte("animaux.txt") )     
              
         print(names(adt))     
              
         print(adt)     
              
              
    
    
         19 mots en tout dont  14  mots distincts.     
         chaque mot est donc répété      1.36 fois en moyenne.     
              
         [1] "nmots"  "hmots"  "nmotsd" "tmots"  "toccs"     
         $nmots     
         [1] 19     
              
         $hmots     
         <hash> containing 14 key-value pair(s).     
           aboie : 1     
           alors : 1     
           animaux : 1     
           avec : 1     
           chat : 2     
           chien : 2     
           des : 1     
           et : 1     
           le : 4     
           miaule : 1     
           pattes : 1     
           quatre : 1     
           que : 1     
           sont : 1     
              
         $nmotsd     
         [1] 14     
              
         $tmots     
                 occ     
         aboie     1     
         alors     1     
         animaux   1     
         avec      1     
         chat      2     
         chien     2     
         des       1     
         et        1     
         le        4     
         miaule    1     
         pattes    1     
         quatre    1     
         que       1     
         sont      1     
              
         $toccs     
                 occ     
         le        4     
         chien     2     
         chat      2     
         sont      1     
         que       1     
         quatre    1     
         pattes    1     
         miaule    1     
         et        1     
         des       1     
         avec      1     
         animaux   1     
         alors     1     
         aboie     1     
              
              
    

    Pour une matrice d'occurences de mots dans des textes, on peut utiliser notre fonction cpt() dont voici un exemple d'utilisation

    
          cpt("bete.txt candide.txt","maison temps train")     
              
    
    
         # au bout d'environ 20 secondes :     
              
          fichier  1  /  2  :  bete.txt     
             23029 mots en tout dont  4238  mots distincts.     
             chaque mot est donc répété      5.43 fois en moyenne.     
              
          fichier  2  /  2  :  candide.txt     
             1958 mots en tout dont  731  mots distincts.     
             chaque mot est donc répété      2.68 fois en moyenne.     
              
                     maison temps train     
         bete.txt        21     9    56     
         candide.txt      3     1     0     
              
    
  7. Voici le code-source des fonctions et des exemples d'utilisation pour bien comprendre comment elles fonctionnnent.

    prems renvoie tous les "premiers" éléments d'un vecteur, c'est-à-dire en fait tous les éléments sauf le dernier.

    derns renvoie tous les "derniers" éléments d'un vecteur, c'est-à-dire tous les éléments sauf le premier.

    affRec affiche récursivement la chaine de caractère qui représente formellement la somme des éléments d'un vecteur. Cette fonction affiche la somme formelle des premiers éléments, obtenue récursivement via prems(), puis le signe plus et enfin le dernier élément.

    Contrairement à affRec, les fonctions somRecCrois et somRecFin calculent effectivement de façon récursive la somme des éléments d'un vecteur. somRecCrois effectue le calcul à partir du premier élément alors que somRecFin commence le calcul à partir du dernier élément.

    
         prems <- function(vect) {     
           # renvoie tous les éléments sauf le dernier     
           return(vect[-length(vect)])     
         } # fin de fonction prems     
              
         derns <- function(vect) {     
           # renvoie tous les éléments sauf le premier     
           return(vect[-1])     
         } # fin de fonction derns     
              
         # exemple d'affichage récursif utilisant prem()     
              
         affRec <- function(vect) {     
           if(length(vect)==1) {     
              return(vect)     
           } else {     
              return(paste(affRec(prems(vect))," + ",vect[length(vect)],sep=""))     
           } # fin de si     
         } # fin de fonction affRec     
              
         somRecCrois <- function(vect,dbg=FALSE) {     
           # somme récursive des éléments de vect à partir du premier     
           if (dbg) { cat("appel de somRecCrois(",vect,")\n") }     
           if(length(vect)==1) {     
              return(vect)     
           } else {     
              return(vect[1]+somRecCrois(derns(vect),dbg))     
           } # fin de si     
         } # fin de fonction somRecCrois     
              
         somRecFin <- function(vect,dbg=FALSE) {     
           # somme récursive des éléments de vect à partir du dernier     
           if (dbg) { cat("appel de somRecFin(",vect,")\n") }     
           if(length(vect)==1) {     
              return(vect)     
           } else {     
              return(somRecFin(prems(vect),dbg)+vect[length(vect)])     
           } # fin de si     
         } # fin de fonction somRecFin     
              
         # vecteur de données et exemples     
              
         v <- 10*(1:5)     
              
         cats("Vecteur v")     
         cat(v,"\n")     
              
         cats("exemple d'affichage récursif ")     
         cat(affRec(v),"\n")     
              
         cats("Vecteur derns(v)")     
         cat(derns(v),"\n")     
              
         cats("Vecteur prems(v)")     
         cat(prems(v),"\n")     
              
         cats("Somme des éléments de v :")     
         cat(sum(v),"\n")     
              
         cats("Somme récursive par le début des éléments de v :")     
         cat(somRecCrois(v),"\n")     
              
         cats("explications")     
         cat(somRecCrois(v,dbg=TRUE),"\n")     
              
         cats("Somme récursive par la fin des éléments de v :")     
         cat(somRecFin(v),"\n")     
              
         cats("explications")     
         cat(somRecFin(v,dbg=TRUE),"\n")     
              
         # on ajoute des parenthèses pour y voir plus clair     
              
         somRecCroisV2 <- function(vect) {     
           if(length(vect)==1) {     
              return(vect)     
           } else {     
              return(paste(vect[1]," + (",somRecCroisV2(derns(vect)),")",sep=""))     
           } # fin de si     
         } # fin de fonction somRecCroisV2     
              
         cats("détails 1")     
         cat(somRecCroisV2(v),"\n")     
              
         somRecFinV2 <- function(vect) {     
           if(length(vect)==1) {     
              return(vect)     
           } else {     
              return(paste("(",somRecFinV2(prems(vect)),") + ",vect[length(vect)],sep=""))     
           } # fin de si     
         } # fin de fonction somRecFinV2     
              
         cats("détails 2")     
         cat(somRecFinV2(v),"\n")     
              
         # tri récursif d'un vecteur : on trouve le minimum, on l'enlève     
         # et on trie ce qui reste     
              
         v <- round(runif(5,1,10),1)     
              
         cats(" vecteur de départ : ")     
         cat(v,"\n")     
              
         triRec <- function(vect) {     
           if (length(vect)==1) {     
             return(vect)     
           } else {     
             mini   <- min(vect)     
             indMin <- which(vect==mini)     
             return(c(mini,triRec(vect[-indMin])))     
             # possible, mais moins lisible :     
             #  } else {     
             #    mini   <- min(vect)     
             #    return(c(mini,triRec(vect[-which(vect==mini)])))     
           } # fin de si     
         } # fin de fonction triRec     
              
         triRecV2 <- function(vect) {     
           if (length(vect)==1) {     
             return(vect)     
           } else {     
             mini   <- min(vect)     
             indMin <- which.min(vect)     
             return(c(mini,triRec(vect[-indMin])))     
           } # fin de si     
         } # fin de fonction triRecV2     
              
         w <- triRec(v)     
         cats(" vecteur trié : ")     
         cat(w,"\n")     
              
         # démonstrations des tris récursifs     
              
         v <- c(2,8,9,2,7,5,8)     
         cat("\nAttention : le triRec de ",v,"est",triRec(v),"\n")     
         cat("\nle triRecV2 de ",v,"est",triRecV2(v),"\n")     
              
              
              
    
    
              
         Vecteur v     
         =========     
              
         10 20 30 40 50     
              
         exemple d'affichage récursif     
         =============================     
              
         10 + 20 + 30 + 40 + 50     
              
         Vecteur derns(v)     
         ================     
              
         20 30 40 50     
              
         Vecteur prems(v)     
         ================     
              
         10 20 30 40     
              
         Somme des éléments de v :     
         =========================     
              
         150     
              
         Somme récursive par le début des éléments de v :     
         ================================================     
              
         150     
              
         explications     
         ============     
              
         appel de somRecCrois( 10 20 30 40 50 )     
         appel de somRecCrois( 20 30 40 50 )     
         appel de somRecCrois( 30 40 50 )     
         appel de somRecCrois( 40 50 )     
         appel de somRecCrois( 50 )     
         150     
              
         Somme récursive par la fin des éléments de v :     
         ==============================================     
              
         150     
              
         explications     
         ============     
              
         appel de somRecFin( 10 20 30 40 50 )     
         appel de somRecFin( 10 20 30 40 )     
         appel de somRecFin( 10 20 30 )     
         appel de somRecFin( 10 20 )     
         appel de somRecFin( 10 )     
         150     
              
         détails 1     
         =========     
              
         10 + (20 + (30 + (40 + (50))))     
              
         détails 2     
         =========     
              
         ((((10) + 20) + 30) + 40) + 50     
              
          vecteur de départ :     
         =====================     
              
         9.5 5.1 6.9 4.5 8.3     
              
          vecteur trié :     
         ================     
              
         4.5 5.1 6.9 8.3 9.5     
              
         Attention : le triRec de  2 8 9 2 7 5 8 est 2 5 7 8 9     
              
         le triRecV2 de  2 8 9 2 7 5 8 est 2 2 5 7 8 9     
              
    

    Comme on peut le voir, une fonction récursive a toujours un test d'arrêt (ou d'initialisation) et un appel à elle-même mais avec un paramètre de longueur inférieure. L'appel récursif peut être la première partie ou la dernière partie de la fonction.

    Avec which(vect==minVec) on trouve (donc on peut supprimer) toutes les occurences du minimum alors que which.min(vect) ne fournit que la première occurence du minimum. Avec which(vect==minVec) on obtient donc un vecteur trié sans doublon, ce qui peut aussi se faire à l'aide des fonctions unique() et duplicated().

  8. Il s'agit de notre fonction decritQT() de statgh.r, bien sûr. Elle a aussi un paramètre de langue, une valeur maximale en y pour l'histogramme des classes etc. Le tracé tige et feuilles et les graphiques sont gérés par l'appel de la fonction plotQTdet().

  9. R est prévu pour s'exécuter en mode dit "BATCH". Donc un script de commandes pour le système d'exploitation suffit à lancer R, exécuter le programme et produire les fichiers de résultats. Toutefois, pour une meilleure portabilité, par exemple en cas de machines différentes (Windows, Linux, MacOs...) il est certainement préférable d'écrire un script dans un langage interactif comme perl ou rexx. Voici, à titre d'exemple notre fichier rstat.rex et des exemples d'utilisation

    
         /*  (gH)   --  rstat.rex  ;  TimeStamp (unix) : 09 Janvier 2003 14:06 */
         
         
         /* ceci exécute R avec un programme passé en paramètre. */
         /* on peut préciser le nom du fichier de sortie         */
         
         parse arg nomprog nomsor
         
         if words(nomprog)=0 then do
            say
            say " syntaxe : rstat [ prog [fichier_sor] ] "
            say
            say " on lance R --no-save < $1 > $ 2 "
            say " rstat r lance R en interactif"
            say
            return
         end /* fin de si */
         
         cmd = " R --no-save --encoding='latin1' "
         if (translate(nomprog)\="R") then cmd = cmd " < " nomprog
         
         if words(nomsor)>0 then do
            cmd = cmd " > " nomsor
         end /* fin de si */
         
         say cmd
         cmd
         
         
    
    
         # appel de R en ligne de commande     
              
         rstat r     
              
         # utilisation d'un programme R nommé test.r en ligne de commandes     
         # (afichage à l'écran)     
              
         rstat test.r     
              
         # utilisation d'un programme R nommé prog.r en ligne de commandes     
         # (afichage dans le fichier prog.sor)     
              
         rstat prog.r prog.sor     
              
              
    

    Si on doit toujours exécuter disons la fonction allQT() sur un jeu de données, le plus simple est d'écrire un script R qui lit toujours le même fichier de données, puis d'adapter le script d'appel pour qu'il recopie le fichier des données de l'utilisateur avec le nom imposé avant d'exécuter ce script R...

    Voici par exemple le programme qtslt.r à utiliser pour analyser le fichier qtslt.dar qui ne contient que des variables quantitatives :

    
         ###########################################     
         #     
         ## analyse du fichier qtslt.dar     
         #     
         ###########################################     
              
         # 1. chargement des fonctions (gH)     
              
         source("statgh.r",encoding="latin1")     
              
         # 2. lecture des données     
              
         qtslt <- lit.dar("qtslt.dar")     
              
         # 3. appel de la fonction allQTdf     
              
         allQTdf(qtslt)     
              
              
    

    Pour utiliser ce programme et analyser vins.dar, voici ce qu'il faut faire sous Windows en ligne de commande :

    
         copy vins.dar qtslt.dar
         "C:\Program Files\R-2.14\bin\i386\Rterm.exe" --no-save < D:\Cours\R\qtslt.r > vins_qtslt.txt
         
    

    Et sous Linux (ou MacOs) :

    
         cp vins.dar qtslt.dar     
         /usr/bin/R  --no-save < ~/Cours/R/qtslt.r > vins_qtslt.txt     
              
    

    Pour utiliser ce programme et analyser iris.dar, voici ce qu'il faut faire sous Windows en ligne de commande :

    
         copy iris.dar qtslt.dar
         "C:\Program Files\R-2.14\bin\i386\Rterm.exe" --no-save < D:\Cours\R\qtslt.r > iris_qtslt.txt
         
    

    Et sous Linux (ou MacOs) :

    
         cp iris.dar qtslt.dar     
         /usr/bin/R  --no-save < ~/Cours/R/qtslt.r > iris_qtslt.txt     
              
    

    Ces commandes à écrire ne sont pas simples et il vaut mieux les éviter, sauf si on est un(e) professionnel(le) de l'informatique. Parmi les défauts qu'on peut leur reprocher, il y a le fait qu'il est difficile de se souvenir des chemins d'accès des logiciels. De plus, il n'est pas toujours évident de maitriser la redirection des entrées avec le caractère < et la redirection des sorties avec le caractère >. Enfin, les copies de noms de fichier "à la main" peuvent être parfois source d'erreurs.

    Pour toutes ces raisons, le plus simple est d'écrire un programme qui s'en occupe à notre place. Voici une solution Rexx/Regina

    
         /*  (gH)   -_-  anaqt_rex.rex  ;  TimeStamp (unix) : 01 Mars 2012 vers 14:42 */
         
         version = 1.0
         
         parse arg nomf
         
         /* rappel de la syntaxe si aucun paramètre */
         
         if words(nomf)=0 then do
            say
            say "  anaqt_rex :  analyse d'un fichier qui ne contient que des QT"
            say "  syntaxe   :  anaqt_rex fichier[.dar] "
            say "  exemples  :  anaqt_rex demo1.dar"
            say "               anaqt_rex demo2    "
            say
            return
         end /* fin de si */
         
         /* préparation des noms de fichier */
         
            /* si le fichier se termine par ., on le retire */
         
            if (substr(nomf,length(nomf),1)=".") then nomf = substr(nomf,1,length(nomf)-1)
         
            /* si le fichier ne se termine pas par .dar (à cause de la complétion via tab) */
            /* on ajoute .dar au nom de fichier */
         
            if (index(nomf,".dar")=0) then nomf = nomf||".dar"
         
         /* on vérifie que le fichier existe */
         
         rf = fileut("checkFile^"nomf)
         if rf = -1 then do
             say "       en conséquence, j'arrête le programme."
            return
         end /* fin de si */
         
         /* on recopie le fichier de données en qtslt.dar*/
         
         cmd = "cp " nomf " qtslt.dar"
         say cmd
         cmd
         
         /* on exécute le programme R avec une sortie dans le fichier standard */
         
         cmd = "rstat qtslt.r qtslt.sor "
         say cmd
         cmd
         
         /* on recopie le fichier de résultats avec un nom plus sympathique */
         
         bn = fileut("fileName^"nomf)
         fs = bn||".sor"
         
         cmd = "cp qtslt.sor " fs
         say cmd
         cmd
         
         /* affichage de fin */
         
         say " vous pouvez utiliser " fs
         
    

    Et une solution Perl

    
         #  (gH)   -_-  anaqt_pl.pl  ;  TimeStamp (unix) : 01 Mars 2012 vers 15:41     
              
         # test du paramètre     
              
         if ($ARGV[0] eq "") {     
              
            print "\n" ;     
            print "  anaqt_pl  :  analyse d'un fichier qui ne contient que des QT \n" ;     
            print "  syntaxe   :  anaqt_pl  fichier[.dar] \n" ;     
            print "  exemples  :  anaqt_pl  demo1.dar \n" ;     
            print "               anaqt_pl  demo2    \n"  ;     
            print "\n" ;     
            exit(-1) ;     
              
         } # fin de si     
              
         $nomf = $ARGV[0] ;     
              
         # préparation des noms de fichier     
              
            # si le fichier se termine par ., on le retire     
              
            if (substr($nomf,length($nomf)-1) eq ".") { $nomf = substr($nomf,0,length($nomf)-1) ; } ;     
              
            #  si le fichier ne se termine pas par .dar (à cause de la complétion via tab)     
            #  on ajoute .dar au nom de fichier     
              
            if (index($nomf,".dar")==-1) { $nomf = $nomf.".dar" ; } ;     
              
         # on vérifie que le fichier existe *     
              
         open(FE,"<$nomf") or die("le fichier $nomf n'existe pas.\n\n") ;     
         close(FE) ;     
              
         # on recopie le fichier de données en qtslt.dar     
              
         $cmd = "cp $nomf qtslt.dar" ;     
         print "$cmd\n" ;     
         system($cmd) ;     
              
         # on exécute le programme R avec une sortie dans le fichier standard     
              
         $cmd = "rstat qtslt.r qtslt.sor " ;     
         print "$cmd\n" ;     
         system($cmd) ;     
              
         # on recopie le fichier de résultats avec un nom plus sympathique     
              
         $bn = substr($nomf,0,rindex($nomf,".")) ;     
         $fs = $bn.".sor" ;     
              
         $cmd = "cp qtslt.sor $fs " ;     
         print "$cmd\n" ;     
         system($cmd) ;     
              
         # affichage de fin     
              
         print "\n vous pouvez utiliser $fs \n\n"     
              
    

    Enfin, si on écrit un script exécutable qui exécute ces programmes, et qui est accessible par le PATH, l'utilisation est encore facilitée, sous Windows, comme sous Linux ou MacOs. Par exemple sous Linux, si on rend exécutable via chmod +x anaqt_rex le fichier suivant nommé anaqt_rex

    
         regina ~gh/Bin/anaqt_rex.rex $*     
              
    

    alors on peut utiliser directement la commande anaqt_rex. En voici la démonstration :

    
         # démonstrations de l'utilisation du script Rexx     
              
         os> anaqt_rex     
              
           anaqt_rex :  analyse d'un fichier qui ne contient que des QT     
           syntaxe   :  anaqt_rex fichier[.dar]     
           exemples  :  anaqt_rex demo1.dar     
                        anaqt_rex demo2     
              
         os> anaqt_rex pommes.dar     
              
           -- ! -- 'Fichier'  pommes.dar  'non vu dans le cd courant !'     
           en conséquence, j'arrête le programme.     
              
         os> anaqt_rex vins.dar     
              
           cp  vins.dar  qtslt.dar     
           rstat qtslt.r qtslt.sor     
           cp qtslt.sor  vins.sor     
              
           vous pouvez utiliser  vins.sor     
              
         os> anaqt_rex iris     
              
           cp  iris.dar  qtslt.dar     
           rstat qtslt.r qtslt.sor     
           cp qtslt.sor  iris.sor     
              
           vous pouvez utiliser  iris.sor     
              
              
    

    Il est clair qu'au vu de la démonstration du package hwriter que l'on pourra consulter ici, fournir les résultats en HTML est une bonne idée puisque les traitements de texte moderne (post 2010) savent ouvrir les fichiers HTML.

    De façon générale, un navigateur permet de visualiser n'importe quel texte, permet de grossir ou de rétrécir la taille des caractères, c'est donc un bon candidat pour afficher des données importantes. C'est pourquoi au lieu de la fonction print() de R, nous préférons utiliser notre fonction hprint() qui affiche les structures dans le navigateur.

  10. La solution consiste à compter le nombre de valeurs distinctes. Il y a en général peu de valeurs pour une QL, et souvent beaucoup plus pour une QT. Pour compter le nombre de valeurs distinctes du vecteur v, on peut utiliser length( unique(v) ). Voici donc la nouvelle fonction lesColonnes() et un exemple d'utilisation :

    
         ################################################################################################     
              
         lesColonnesV1 <- function(df,envar=FALSE,print=TRUE,order=TRUE) {     
              
         ################################################################################################     
              
         nbc  <- ncol(df)     
         nbl  <- nrow(df)     
         cat("Voici les ",nbc,"colonnes (stat. sur ",nbl," lignes en tout)\n\n")     
         noms <- names(df)     
         nbvs <- rep(NA,nbc)     
         mins <- rep(NA,nbc)     
         maxs <- rep(NA,nbc)     
         ddc <- cbind((1:nbc),nbvs,mins,maxs)     
         row.names(ddc) <- noms     
         colnames(ddc) <- c("Num","NbVal","Min","Max")     
         pdc <- 1:nbc     
         for (idc in pdc) {     
           laCol <- as.numeric(df[,idc])     
           laCol <- laCol[!is.na(laCol)]     
           ddc[idc,2] <- length(laCol)     
              ddc[idc,3] <- min(laCol)     
              ddc[idc,4] <- max(laCol)     
         } # fin pour     
              
         if (order) { # tri par ordre alphabétique des noms de variables     
           idx <- order(noms)     
           ddc <- ddc[idx,]     
         } # fin si     
              
         print.data.frame(as.data.frame(ddc),quote=FALSE,row.names=TRUE)     
         cat("\n")     
              
         if (envar) {     
            return(as.data.frame(ddc))     
         } else {     
            return()     
         } # fin de si     
              
         } # fin de fonction lesColonnesV1     
              
         ##############################################################################     
              
         lesColonnesV2 <- function(df,envar=FALSE,print=TRUE,ordered=TRUE) {     
              
         #################################################################     
              
         nbc  <- ncol(df)     
         nbl  <- nrow(df)     
         cat("Voici l'analyse des ",nbc,"colonnes (stat. sur ",nbl," lignes en tout)\n\n")     
         noms <- names(df)     
         nbvs <- rep(NA,nbc)     
         mins <- rep(NA,nbc)     
         maxs <- rep(NA,nbc)     
         dist <- rep(NA,nbc)     
         ddc <- cbind((1:nbc),nbvs,mins,maxs,dist)     
         row.names(ddc) <- noms     
         colnames(ddc) <- c("Num","NbVal","Min","Max","Distinct")     
         pdc <- 1:nbc     
         for (idc in pdc) {     
            laCol <- as.numeric(df[,idc])     
            laCol <- laCol[!is.na(laCol)]     
            ddc[idc,2] <- length(laCol)     
            ddc[idc,3] <- min(laCol)     
            ddc[idc,4] <- max(laCol)     
            ddc[idc,5] <- length(unique(laCol))     
         } # fin pour     
              
         if (ordered) { # tri par ordre alphabétique des noms de variables     
           idx <- order(noms)     
           ddc <- ddc[idx,]     
         } # fin si     
              
         print.data.frame(as.data.frame(ddc),quote=FALSE,row.names=TRUE)     
         cat("\n")     
              
         if (envar) {     
            return(as.data.frame(ddc))     
         } else {     
            return()     
         } # fin de si     
              
         } # fin de fonction lesColonnesV2     
              
         #################################################################     
              
         # démonstration :     
              
         datagh("elf")     
              
         cats("ancienne version")     
         lesColonnesV1(elfdata)     
              
         cats("nouvelle version")     
         lesColonnesV2(elfdata)     
              
              
    
    
              
          DOSSIER  elf (après lecture de  /home/gh/public_html/Datasets/elf.dar ) :     
              
          Vous pouvez utiliser la matrice elfdata et les vecteurs     
            ids(TXT)  sexe (QLnum), sexe_(QLstr), age (QT),  etud (QLnum), etud_ (QLstr)     
              
            - les modalités sont nommées m_sexe m_etud     
            - les unités    sont nommées u_age     
            - les intitulés sont nommées t_sexe t_age t_etud     
              
         ancienne version     
         ================     
              
         Voici les  6 colonnes (stat. sur  99  lignes en tout)     
              
              Num NbVal Min Max     
         AGE    2    99  11  78     
         ETUD   4    99   0   4     
         PROF   3    99   0  16     
         REGI   5    99   0   4     
         SEXE   1    99   0   1     
         USAG   6    99   0   3     
              
         NULL     
              
         nouvelle version     
         ================     
              
         Voici l'analyse des  6 colonnes (stat. sur  99  lignes en tout)     
              
              Num NbVal Min Max valDistinct     
         AGE    2    99  11  78          50     
         ETUD   4    99   0   4           5     
         PROF   3    99   0  16          13     
         REGI   5    99   0   4           5     
         SEXE   1    99   0   1           2     
         USAG   6    99   0   3           4     
              
         NULL     
              
    

    Cette fonction fait bien sur partie de statgh.r et se nomme lesColonnes().

  11. Le problème est assez simple, puisqu'on veut seulement retirer des variables fortement corrélées. Deux boucles pour qui passent en revue la matrice triangulaire inférieure (ou supérieure) des coefficients de corrélation suffisent à repérer les variables à retirer, mises (via leur numéro de colonne) par notre programme dans le vecteur colasup. Une fois connues ces colonnes, on peut les retirer du jeu de données initial.

    Il serait maladroit de vouloir imposer d'utiliser la corrélation de Kendall, ou de Spearman. Le mieux est de faire comme la fonction cor() : on laisse le choix de la méthode, avec la valeur "pearson" par défaut.

    La notion de forte corrélation est très subjective. Utiliser le test de corrélation significative cor.test() est une solution un peu biaisée puisque ce test tend à trouver toute corrélation significative quand n est grand. Du coup, un seuil arbitraire mais variable et fixé par l'utilisateur est un choix raisonnable. Enfin, mettre les données réduites dans un nouveau fichier est sans doute une option utile, d'où les quatre paramètres utilisés par notre fonction...

    
         #################################################################     
              
         reduitVarsCor <- function(matdata,rho=0.8,file="",methode="pearson") {     
              
         #################################################################     
              
         # on retire les variables fortement corrélées     
              
         if (missing(matdata)) {     
           cat(" reduitVars : élimine les colonnes linéairement corrélées à plus de rho, fourni en paramètre\n")     
           cat("              (valeur par défaut : 0.8)\n")     
           cat(" syntaxe : reduitVars(matdata,rho=0.8,file=\"\",methode=\"pearson\") \n\n")     
           stop()     
         } ; # fin si     
              
         cat("\nRéduction du nombre de variables par suppression des variables fortement corrélées au seuil rho=",rho)     
         cat("\npour la corrélation de ",methode,"\n\n")     
              
         matdataorg <- matdata     
         nbcol      <- ncol(matdata)     
         colasup    <- c() # indices des colonnes à supprimer     
              
         for (i in 1:(nbcol-1)) {     
           vi   <- matdata[,i]     
           nomi <- sprintf("%-12s",names(matdata)[i])     
           for (j in (i+1):nbcol) {     
                  vj    <- matdata[,j]     
                  corij <- cor(vi,vj,use="pairwise.complete.obs",method=methode)     
                  if (abs(corij)>=rho) {     
                     nomj <- sprintf("%-12s",names(matdata)[j])     
                     cat("  la colonne ",sprintf("%5d",j)," soit ",nomj," est éliminée car fortement corrélée à ")     
                     cat("la colonne ",sprintf("%5d",i)," soit ",nomi," : rho = ",sprintf("%6.3f",corij),"\n")     
                     colasup <- c(colasup,j)     
                  } # fin de si     
           } # fin pour j     
         } # fin pour i     
              
         newmatdata <- matdata     
         cat("  réduction : ")     
         nbcolasup <- length(colasup)     
         if (nbcolasup>0) {     
            nbcolasup <- length(colasup)     
            if (nbcolasup==1) {     
               cat(nbcolasup," colonne fortement corrélée linéairement supprimée \n")     
            }  else {     
               cat(nbcolasup," colonnes fortement corrélées linéairement supprimées \n")     
            } # fin si     
            #print( colasup )     
              
            ######################################################     
            #     
            # NE PAS ECRIRE     
            #     
            #  colasup <- rev(sort(unique(colasup)))     
            #     
            #  for (jcol in colasup) {     
            #      newmatdata <- newmatdata[,-jcol]     
            #  } # fin pour jcol     
            #     
            ######################################################     
            #     
            # MAIS PLUTOT :     
            #     
              
            newmatdata <- newmatdata[,-colasup]     
              
         } else {     
            cat(" pas de colonnes fortement corrélées linéairement supprimées \n")     
         } # fin si     
              
         # recherche de la plus forte corrélation restante     
              
         # affichage des dimensions avant et après     
              
         cat("\nRésumé des dimensions\n")     
         cat(" données initiales : ",sprintf("%5d",dim(matdataorg)),"\n")     
         cat(" données finales   : ",sprintf("%5d",dim(newmatdata)),"\n\n")     
              
         nomi   <- colnames(newmatdata)[1]     
         nomj   <- colnames(newmatdata)[1]     
         maxcor <- 0     
              
         nbcol <- ncol(newmatdata)     
              
         for (i in 1:(nbcol-1)) {     
           vi <- newmatdata[,i]     
           for (j in (i+1):nbcol) {     
                  vj    <- newmatdata[,j]     
                  corij <- cor(vi,vj,use="pairwise.complete.obs",method=methode)     
                  if (abs(corij)>=abs(maxcor)) {     
                     maxcor <- corij     
                     imax <- i     
                     jmax <- j     
                     nomi <- colnames(newmatdata)[i]     
                     nomj <- colnames(newmatdata)[j]     
                  } # fin de si     
           } # fin pour j     
         } # fin pour i     
              
         cat(" le plus fort coefficient de corrélation restant est ",sprintf("%6.3f",maxcor),"\n")     
         cat(" et met en jeu les colonnes ",imax," et ",jmax," soit ",nomi," et ",nomj,"\n\n")     
              
         if (file!="")  {     
           write.table(newmatdata,file=file,quote=FALSE,)     
           cat("les données finales ont été écrites dans le fichier ",file,"\n")     
         } ; # fin si     
              
         return(newmatdata)     
              
         } # fin de fonction reduitVarsCor     
              
         #################################################################     
              
         # exemple d'utilisation :     
              
         lea <- lit.dar("leadb710x46.dar.txt")[ ,-1]  # sans la colonne 1 !     
              
         leaReduit <- reduitVarsCor(matdata=lea,rho=0.8,methode=methode)     
              
              
              
    
    
              
         Réduction du nombre de variables par suppression des variables fortement corrélées au seuil rho= 0.8     
         pour la corrélation de  pearson     
              
           la colonne      3  soit  MW            est éliminée car fortement corrélée à la colonne      1  soit  Length        : rho =   0.995     
           la colonne      6  soit  Netcharge     est éliminée car fortement corrélée à la colonne      2  soit  pI            : rho =   0.923     
           la colonne     38  soit  D.E.K.R.1     est éliminée car fortement corrélée à la colonne      2  soit  pI            : rho =  -0.911     
           la colonne      5  soit  Gravy         est éliminée car fortement corrélée à la colonne      4  soit  Foldindex     : rho =   0.987     
           la colonne      8  soit  Hydrophobi    est éliminée car fortement corrélée à la colonne      4  soit  Foldindex     : rho =   0.879     
           la colonne     11  soit  Buried        est éliminée car fortement corrélée à la colonne      4  soit  Foldindex     : rho =   0.811     
           la colonne     13  soit  Transmembr    est éliminée car fortement corrélée à la colonne      4  soit  Foldindex     : rho =   0.905     
           la colonne      8  soit  Hydrophobi    est éliminée car fortement corrélée à la colonne      5  soit  Gravy         : rho =   0.873     
           la colonne     13  soit  Transmembr    est éliminée car fortement corrélée à la colonne      5  soit  Gravy         : rho =   0.887     
           la colonne     38  soit  D.E.K.R.1     est éliminée car fortement corrélée à la colonne      6  soit  Netcharge     : rho =  -0.997     
           la colonne      8  soit  Hydrophobi    est éliminée car fortement corrélée à la colonne      7  soit  Hydrophili    : rho =  -0.896     
           la colonne     13  soit  Transmembr    est éliminée car fortement corrélée à la colonne      7  soit  Hydrophili    : rho =  -0.936     
           la colonne     17  soit  E.Unip        est éliminée car fortement corrélée à la colonne      7  soit  Hydrophili    : rho =   0.855     
           la colonne     35  soit  D.E           est éliminée car fortement corrélée à la colonne      7  soit  Hydrophili    : rho =   0.856     
           la colonne     36  soit  K.R           est éliminée car fortement corrélée à la colonne      7  soit  Hydrophili    : rho =   0.850     
           la colonne     37  soit  D.E.K.R       est éliminée car fortement corrélée à la colonne      7  soit  Hydrophili    : rho =   0.918     
           la colonne     11  soit  Buried        est éliminée car fortement corrélée à la colonne      8  soit  Hydrophobi    : rho =   0.832     
           la colonne     13  soit  Transmembr    est éliminée car fortement corrélée à la colonne      8  soit  Hydrophobi    : rho =   0.926     
           la colonne     39  soit  A.I.L.V       est éliminée car fortement corrélée à la colonne      9  soit  Flexibility   : rho =  -0.828     
           la colonne     15  soit  G.Unip        est éliminée car fortement corrélée à la colonne     10  soit  Bulkiness     : rho =  -0.882     
           la colonne     13  soit  Transmembr    est éliminée car fortement corrélée à la colonne     11  soit  Buried        : rho =   0.868     
           la colonne     35  soit  D.E           est éliminée car fortement corrélée à la colonne     17  soit  E.Unip        : rho =   0.864     
           la colonne     37  soit  D.E.K.R       est éliminée car fortement corrélée à la colonne     17  soit  E.Unip        : rho =   0.870     
           la colonne     37  soit  D.E.K.R       est éliminée car fortement corrélée à la colonne     19  soit  K.Unip        : rho =   0.810     
           la colonne     42  soit  S.T           est éliminée car fortement corrélée à la colonne     25  soit  T.Unip        : rho =   0.807     
           la colonne     41  soit  N.Q           est éliminée car fortement corrélée à la colonne     32  soit  Q.Unip        : rho =   0.903     
           la colonne     37  soit  D.E.K.R       est éliminée car fortement corrélée à la colonne     35  soit  D.E           : rho =   0.949     
           la colonne     37  soit  D.E.K.R       est éliminée car fortement corrélée à la colonne     36  soit  K.R           : rho =   0.904     
           la colonne     45  soit  C.F.Y.W       est éliminée car fortement corrélée à la colonne     40  soit  F.W.Y         : rho =   0.967     
           réduction : 16  colonnes fortement corrélées linéairement supprimées     
              
         Résumé des dimensions     
          données initiales :    710    45     
          données finales   :    710    29     
              
          le plus fort coefficient de corrélation restant est   0.796     
          et met en jeu les colonnes  4  et  11  soit  Hydrophili  et  K.Unip     
              
              
    
  12. Le problème n'est pas simple, et en tous cas beaucoup plus compliqué qu'à la question précédente. En effet, si X et Y sont corrélées, il est possible que Y soit aussi corrélée à Z sans que X ne soit corrélée à Z car il n'y a pas transitivité, comme on dit en mathématique, de la notion de corrélation. Une solution consiste, à partir d'une variable, lui adjoindre toutes celles qui lui sont fortement corrélées, puis à calculer la clotûre transitive, c'est-à-dire ajouter aussi les autres variables qui sont fortement corrélées aux variables qu'on vient d'ajouter et de recommencer tant qu'on ajoute des variables...

    Dans le programme qui suit, on utilise 2 vecteurs nommés colatrait et colvues. Au départ, colatrait vaut 1 pour toutes les variables et on met 0 dans colatrait[j] quand on traité la variable j. Il y a donc une boucle principale basée sur le nombre de variables encore à 1 dans colatrait.

    Le tableau colvues permet de savoir quel est l'état de la variable : déjà traitée, en cours ou non encore vue. Afin de savoir quelles variables sont directement corrélées et celles qui sont ajoutées ensuite, notre fonction insère une étoile pour la corrélation directe et deux étoiles pour la corrélation transitive.

    
         ###################################################################################     
              
         corClust <- function(data,seuil=0.8,methode="pearson",detail=FALSE) {     
              
         ###################################################################################     
              
         # on regroupe transitivement les variables fortement corrélées     
              
         if (missing(data)) {     
           cat(" corClust : regroupe les colonnes linéairement corrélées pour rho supérieur au seuil fourni en paramètre\n")     
           cat("              (valeur par défaut : 0.8)\n")     
           cat(" syntaxe : corClust(matdata,seuil=0.8,methode=\"pearson\") \n\n")     
           stop()     
         } ; # fin si     
              
         matdata <- data     
         rho     <- seuil     
              
         cat("Regroupement transitif de variables fortement corrélées au seuil rho=",rho,"\n")     
         cat("pour la corrélation de ",methode,"\n")     
              
         nbcol     <- ncol(matdata)     
         nomcol    <- names(matdata)     
         colatrait <- rep(1,nbcol)     
         colvues   <- rep(2,nbcol) # 2 : colonne non vue, 1 en cours, 0 déja traitée     
         lesgrp    <- rep(0,nbcol) # numéro du groupe     
              
         # on passe les colonnes en revue : celles qui sont à rho>seuil sont mises     
         # ensemble (une étoile) ; on met alors colatrait (colonnes à traiter) à 0 et on     
         # recommence avec les variables du groupe par transitivité (deux étoiles) jusqu'à saturation     
         # puis on passe au groupe suivant ...     
              
         nb1 <- sum(colatrait==1)     
         grp <- 0 # numéro de groupe     
         while (nb1>0) {     
              ibase <- 1     
              while (ibase<=nbcol) {     
                if (colatrait[ibase]==1) {     
                    itrait <- ibase     
                    ibase  <- nbcol + 1     
                } # fin de si sur colonne à traiter     
                ibase <- ibase + 1     
              } # fin tant que sur ibase     
              grp <- grp + 1     
              eff <- 1     
              vi  <- matdata[,itrait]     
              colvues[itrait] <- 0     
              cat("\nGroupe ",sprintf("%2d",grp)," : ")     
              cat("  ",nomcol[itrait])     
              lesgrp[itrait] <- grp     
              if (itrait<=nbcol) {     
                 colatrait[itrait] <- 0     
              
                 # premier passage     
              
                 eff <- 0     
                 for (j in (itrait+1):nbcol) {     
                        vj    <- matdata[,j]     
                        corij <- cor(vi,vj,use="pairwise.complete.obs",method=methode)     
                        if (abs(corij)>=rho) {     
                           colvues[j]   <- 1     
                           cat("  *",nomcol[j])     
                           lesgrp[j] <- grp     
                           eff <- eff + 1     
                        } # fin de si     
                 } # fin pour j     
              
                 # deuxieme passage (transitivité faible de rho)     
              
                 nb2    <- sum(colvues==1)     
                 jtrait <- nbcol+1     
                 while (nb2>0) {     
                   jbase <- 1     
                   while (jbase<=nbcol) {     
                     if ( (colvues[jbase]==1) & (colatrait[jbase]==1) ) {     
                       jtrait <- jbase     
                       jbase  <- nbcol + 1     
                       colvues[jtrait]   <- 0     
                       colatrait[jtrait] <- 0     
                     } # fin de si sur colonne à traiter     
                     jbase <- jbase + 1     
                   } # fin tant que sur jbase     
              
                   nb3 <- sum(colvues==1)     
                   if (jtrait<=nbcol) {     
                      vjt <- matdata[,jtrait]     
                      for (j in (1:nbcol)) {     
                      if (colvues[j]==2) {     
                          if (colatrait[j]==1) {     
                           vj    <- matdata[,j]     
                           corij <- cor(vjt,vj,use="pairwise.complete.obs",method=methode)     
                           if (abs(corij)>=rho) {     
                              colvues[j]   <- 1     
                              cat("  **",nomcol[j])     
                              lesgrp[j] <- grp     
                           } # fin de si     
                          } # fin de si     
                      } # fin de si     
                      } # fin pour j     
                   } # fin si     
                   nb2 <- sum(colvues==1)     
                 } # fin de tant que     
              
              } # fin de si on a au moins une colonne à traiter     
              
              nb1 <- sum(colatrait==1)     
              
         } # fin de tant que     
         cat("\n")     
              
         # mise en forme des résultats     
              
         retenue <- rep(0,nbcol)     
         gard    <- rep(0,grp)     
         for (igrp in (1:grp)) {     
           icol  <- 1     
           igard <- 0     
           while (icol<=nbcol) {     
             if (lesgrp[icol]==igrp) {     
               igard <- icol     
               icol  <- nbcol + 1     
             } # fin si     
             icol <- icol + 1     
           } # fin tant que     
           gard[igrp]     <- igard     
           retenue[igard] <- igrp     
         } # fin pour igrp     
              
         mret            <- cbind(lesgrp,retenue)     
         row.names(mret) <- names(matdata)     
         colnames(mret)  <- c("Groupe","Variable retenue")     
              
         if (detail) {     
              
              cat("\n")     
              cat("Numéros de groupe de corrélation et variable retenue : \n")     
              print(mret)     
              cat("\n")     
              cat("On retient ",grp," variables :")     
              
         } # fin si     
              
         garde <- matdata[,gard]     
              
         cat("\nRésumé des dimensions\n")     
         cat(" données initiales : ",sprintf("%5d",dim(matdata)),"\n")     
         cat(" données finales   : ",sprintf("%5d",dim(garde)),"\n\n")     
              
         if (detail) {     
           return(garde)     
         } # fin si     
              
         } # fin de fonction corClust     
              
         #################################################################     
              
         # exemple d'utilisation :     
              
         lea <- lit.dar("leadb710x46.dar.txt")[ ,-1]  # sans la colonne 1 !     
              
         corClust(data=lea,seuil=0.8,methode="pearson",detail=TRUE)     
              
              
              
    
    
              
         Regroupement transitif de variables fortement corrélées au seuil rho= 0.8     
         pour la corrélation de  pearson     
              
         Groupe   1  :    Length  * MW     
         Groupe   2  :    pI  * Netcharge  * D.E.K.R.1     
         Groupe   3  :    Foldindex  * Gravy  * Hydrophobi  * Buried  * Transmembr  ** Hydrophili  ** E.Unip  ** D.E  ** K.R  ** D.E.K.R  ** K.Unip     
         Groupe   4  :    Flexibility  * A.I.L.V     
         Groupe   5  :    Bulkiness  * G.Unip     
         Groupe   6  :    Accres     
         Groupe   7  :    MW.Length     
         Groupe   8  :    D.Unip     
         Groupe   9  :    R.Unip     
         Groupe  10  :    A.Unip     
         Groupe  11  :    L.Unip     
         Groupe  12  :    I.Unip     
         Groupe  13  :    V.Unip     
         Groupe  14  :    S.Unip     
         Groupe  15  :    T.Unip  * S.T     
         Groupe  16  :    C.Unip     
         Groupe  17  :    M.Unip     
         Groupe  18  :    F.Unip     
         Groupe  19  :    W.Unip     
         Groupe  20  :    Y.Unip     
         Groupe  21  :    N.Unip     
         Groupe  22  :    Q.Unip  * N.Q     
         Groupe  23  :    P.Unip     
         Groupe  24  :    H.Unip     
         Groupe  25  :    F.W.Y  * C.F.Y.W     
         Groupe  26  :    C.W     
         Groupe  27  :    R.E.S.P     
              
         Numéros de groupe de corrélation et variable retenue :     
                     Groupe Variable retenue     
         Length           1                1     
         pI               2                2     
         MW               1                0     
         Foldindex        3                3     
         Gravy            3                0     
         Netcharge        2                0     
         Hydrophili       3                0     
         Hydrophobi       3                0     
         Flexibility      4                4     
         Bulkiness        5                5     
         Buried           3                0     
         Accres           6                6     
         Transmembr       3                0     
         MW.Length        7                7     
         G.Unip           5                0     
         D.Unip           8                8     
         E.Unip           3                0     
         R.Unip           9                9     
         K.Unip           3                0     
         A.Unip          10               10     
         L.Unip          11               11     
         I.Unip          12               12     
         V.Unip          13               13     
         S.Unip          14               14     
         T.Unip          15               15     
         C.Unip          16               16     
         M.Unip          17               17     
         F.Unip          18               18     
         W.Unip          19               19     
         Y.Unip          20               20     
         N.Unip          21               21     
         Q.Unip          22               22     
         P.Unip          23               23     
         H.Unip          24               24     
         D.E              3                0     
         K.R              3                0     
         D.E.K.R          3                0     
         D.E.K.R.1        2                0     
         A.I.L.V          4                0     
         F.W.Y           25               25     
         N.Q             22                0     
         S.T             15                0     
         C.W             26               26     
         R.E.S.P         27               27     
         C.F.Y.W         25                0     
              
         On retient  27  variables :     
         Résumé des dimensions     
          données initiales :    710    45     
          données finales   :    710    27     
              
              
         [... données non affichées]     
              
    

    Pour comprendre ce qu'a fait le programme, on peut calculer la matrice des corrélations des variables du groupe 3 :

    
         lea <- lit.dar("leadb710x46.dar.txt")[ ,-1]  # sans la colonne 1 !     
              
         # démonstration avec le groupe 3     
              
         nomvar <- c("Foldindex","Gravy","Hydrophobi","Buried","Transmembr","Hydrophili","E.Unip","D.E","K.R","D.E.K.R","K.Unip")     
         varcor <- lea[ , nomvar ]     
         mdc(varcor)     
              
              
    
    
              
         Matrice des corrélations au sens de  Pearson pour  710  lignes et  11  colonnes     
              
                    Foldindex  Gravy Hydrophobi Buried Transmembr Hydrophili E.Unip   D.E   K.R D.E.K.R K.Unip     
         Foldindex      1.000     
         Gravy          0.987  1.000     
         Hydrophobi     0.879  0.873      1.000     
         Buried         0.811  0.774      0.832  1.000     
         Transmembr     0.905  0.887      0.926  0.868      1.000     
         Hydrophili    -0.748 -0.719     -0.896 -0.766     -0.936      1.000     
         E.Unip        -0.541 -0.490     -0.678 -0.664     -0.738      0.855  1.000     
         D.E           -0.446 -0.394     -0.605 -0.633     -0.721      0.856  0.864 1.000     
         K.R           -0.477 -0.439     -0.768 -0.670     -0.716      0.850  0.735 0.723 1.000     
         D.E.K.R       -0.494 -0.444     -0.725 -0.698     -0.773      0.918  0.870 0.949 0.904   1.000     
         K.Unip        -0.536 -0.494     -0.628 -0.729     -0.786      0.796  0.682 0.723 0.793   0.810  1.000     
              
    

    La variable à traiter au départ était Foldindex. Le premier passage est venu ajouter les 4 variables Gravy Hydrophobi Buried Transmembr car leur rho avec Foldindex est supérieur à 0,8. Ensuite, la variable à traiter est Gravy mais elle n'ajoute aucune variable. Puis on traite Hydrophobi qui ajoute Hydrophili...

    Il est possible d'ajouter une variable en paramètre pour afficher le suivi des ajouts de corrélation :

    
         ###################################################################################     
              
         corClust <- function(data,seuil=0.8,methode="pearson",detail=FALSE,suivi=FALSE) {     
              
         ###################################################################################     
              
         # on regroupe transitivement les variables fortement corrélées     
              
         if (missing(data)) {     
           cat(" corClust : regroupe les colonnes linéairement corrélées pour rho supérieur au seuil fourni en paramètre\n")     
           cat("              (valeur par défaut : 0.8)\n")     
           cat(" syntaxe : corClust(matdata,seuil=0.8,methode=\"pearson\") \n\n")     
           stop()     
         } ; # fin si     
              
         matdata <- data     
         rho     <- seuil     
              
         cat("Regroupement transitif de variables fortement corrélées au seuil rho=",rho,"\n")     
         cat("pour la corrélation de ",methode,"\n")     
              
         nbcol     <- ncol(matdata)     
         nomcol    <- names(matdata)     
         colatrait <- rep(1,nbcol)     
         colvues   <- rep(2,nbcol) # 2 : colonne non vue, 1 en cours, 0 déja traitée     
         lesgrp    <- rep(0,nbcol) # numéro du groupe     
              
         # on passe les colonnes en revue : celles qui sont à rho>seuil sont mises     
         # ensemble (une étoile) ; on met alors colatrait (colonnes à traiter) à 0 et on     
         # recommence avec les variables du groupe par transitivité (deux étoiles) jusqu'à saturation     
         # puis on passe au groupe suivant ...     
              
         nb1 <- sum(colatrait==1)     
         grp <- 0 # numéro de groupe     
         while (nb1>0) {     
              ibase <- 1     
              while (ibase<=nbcol) {     
                if (colatrait[ibase]==1) {     
                    itrait <- ibase     
                    ibase  <- nbcol + 1     
                } # fin de si sur colonne à traiter     
                ibase <- ibase + 1     
              } # fin tant que sur ibase     
              grp <- grp + 1     
              eff <- 1     
              vi  <- matdata[,itrait]     
              colvues[itrait] <- 0     
              cat("\nGroupe ",sprintf("%2d",grp)," : ")     
         if (suivi) { cat(" basé sur ") }     
              cat("  ",nomcol[itrait])     
         if (suivi) { cat("\n") }     
              lesgrp[itrait] <- grp     
              if (itrait<=nbcol) {     
                 colatrait[itrait] <- 0     
              
                 # premier passage     
              
         if (suivi) { cat(" variables corrélées directement    : ") }     
                 eff <- 0     
                 for (j in (itrait+1):nbcol) {     
                        vj    <- matdata[,j]     
                        corij <- cor(vi,vj,use="pairwise.complete.obs",method=methode)     
                        if (abs(corij)>=rho) {     
                           colvues[j]   <- 1     
                           cat("  *",nomcol[j])     
                           lesgrp[j] <- grp     
                           eff <- eff + 1     
                        } # fin de si     
                 } # fin pour j     
         if (suivi) { cat("\n") }     
              
                 # deuxieme passage (transitivité faible de rho)     
              
         if (suivi) { cat(" variables corrélées transitivement : \n") }     
                 nb2    <- sum(colvues==1)     
                 jtrait <- nbcol+1     
                 while (nb2>0) {     
                   jbase <- 1     
                   while (jbase<=nbcol) {     
                     if ( (colvues[jbase]==1) & (colatrait[jbase]==1) ) {     
                       jtrait <- jbase     
                       jbase  <- nbcol + 1     
                       colvues[jtrait]   <- 0     
                       colatrait[jtrait] <- 0     
                     } # fin de si sur colonne à traiter     
                     jbase <- jbase + 1     
                   } # fin tant que sur jbase     
              
                   nb3 <- sum(colvues==1)     
                   if (jtrait<=nbcol) {     
                      vjt <- matdata[,jtrait]     
                      for (j in (1:nbcol)) {     
                      if (colvues[j]==2) {     
                          if (colatrait[j]==1) {     
                           vj    <- matdata[,j]     
                           corij <- cor(vjt,vj,use="pairwise.complete.obs",method=methode)     
                           if (abs(corij)>=rho) {     
                              colvues[j]   <- 1     
         if (suivi) { cat("   ",nomcol[jtrait]) }     
                              cat("  **",nomcol[j])     
         if (suivi) { cat("\n") }     
                              lesgrp[j] <- grp     
                           } # fin de si     
                          } # fin de si     
                      } # fin de si     
                      } # fin pour j     
                   } # fin si     
                   nb2 <- sum(colvues==1)     
                 } # fin de tant que     
         if (suivi) { cat("\n") }     
              
              } # fin de si on a au moins une colonne à traiter     
              
              nb1 <- sum(colatrait==1)     
              
         # pour debug : attends()     
              
         } # fin de tant que     
         cat("\n")     
              
         # mise en forme des résultats     
              
         retenue <- rep(0,nbcol)     
         gard    <- rep(0,grp)     
         for (igrp in (1:grp)) {     
           icol  <- 1     
           igard <- 0     
           while (icol<=nbcol) {     
             if (lesgrp[icol]==igrp) {     
               igard <- icol     
               icol  <- nbcol + 1     
             } # fin si     
             icol <- icol + 1     
           } # fin tant que     
           gard[igrp]     <- igard     
           retenue[igard] <- igrp     
         } # fin pour igrp     
              
         mret            <- cbind(lesgrp,retenue)     
         row.names(mret) <- names(matdata)     
         colnames(mret)  <- c("Groupe","Variable retenue")     
              
         if (detail) {     
              
              cat("\n")     
              cat("Numéros de groupe de corrélation et variable retenue : \n")     
              print(mret)     
              cat("\n")     
              cat("On retient ",grp," variables :")     
              
         } # fin si     
              
         garde <- matdata[,gard]     
              
         cat("\nRésumé des dimensions\n")     
         cat(" données initiales : ",sprintf("%5d",dim(matdata)),"\n")     
         cat(" données finales   : ",sprintf("%5d",dim(garde)),"\n\n")     
              
         if (detail) {     
           return(garde)     
         } # fin si     
              
         } # fin de fonction corClust     
              
         #################################################################     
              
         # exemple d'utilisation :     
              
         lea       <- lit.dar("leadb710x46.dar.txt")[ ,-1]  # sans la colonne 1 !     
         leaReduit <- corClust(data=lea,seuil=0.8,methode="pearson",suivi=TRUE)     
              
              
    
    
         Regroupement transitif de variables fortement corrélées au seuil rho= 0.8     
         pour la corrélation de  pearson     
              
         Groupe   1  :  basé sur    Length     
          variables corrélées directement    :   * MW     
          variables corrélées transitivement :     
              
              
         Groupe   2  :  basé sur    pI     
          variables corrélées directement    :   * Netcharge  * D.E.K.R.1     
          variables corrélées transitivement :     
              
              
         Groupe   3  :  basé sur    Foldindex     
          variables corrélées directement    :   * Gravy  * Hydrophobi  * Buried  * Transmembr     
          variables corrélées transitivement :     
             Hydrophobi  ** Hydrophili     
             Hydrophili  ** E.Unip     
             Hydrophili  ** D.E     
             Hydrophili  ** K.R     
             Hydrophili  ** D.E.K.R     
             D.E.K.R  ** K.Unip     
              
              
         Groupe   4  :  basé sur    Flexibility     
          variables corrélées directement    :   * A.I.L.V     
          variables corrélées transitivement :     
              
              
         Groupe   5  :  basé sur    Bulkiness     
          variables corrélées directement    :   * G.Unip     
          variables corrélées transitivement :     
              
              
         Groupe   6  :  basé sur    Accres     
          variables corrélées directement    :     
          variables corrélées transitivement :     
              
              
         Groupe   7  :  basé sur    MW.Length     
          variables corrélées directement    :     
          variables corrélées transitivement :     
              
              
         Groupe   8  :  basé sur    D.Unip     
          variables corrélées directement    :     
          variables corrélées transitivement :     
              
              
         Groupe   9  :  basé sur    R.Unip     
          variables corrélées directement    :     
          variables corrélées transitivement :     
              
              
         Groupe  10  :  basé sur    A.Unip     
          variables corrélées directement    :     
          variables corrélées transitivement :     
              
              
         Groupe  11  :  basé sur    L.Unip     
          variables corrélées directement    :     
          variables corrélées transitivement :     
              
              
         Groupe  12  :  basé sur    I.Unip     
          variables corrélées directement    :     
          variables corrélées transitivement :     
              
              
         Groupe  13  :  basé sur    V.Unip     
          variables corrélées directement    :     
          variables corrélées transitivement :     
              
              
         Groupe  14  :  basé sur    S.Unip     
          variables corrélées directement    :     
          variables corrélées transitivement :     
              
              
         Groupe  15  :  basé sur    T.Unip     
          variables corrélées directement    :   * S.T     
          variables corrélées transitivement :     
              
              
         Groupe  16  :  basé sur    C.Unip     
          variables corrélées directement    :     
          variables corrélées transitivement :     
              
              
         Groupe  17  :  basé sur    M.Unip     
          variables corrélées directement    :     
          variables corrélées transitivement :     
              
              
         Groupe  18  :  basé sur    F.Unip     
          variables corrélées directement    :     
          variables corrélées transitivement :     
              
              
         Groupe  19  :  basé sur    W.Unip     
          variables corrélées directement    :     
          variables corrélées transitivement :     
              
              
         Groupe  20  :  basé sur    Y.Unip     
          variables corrélées directement    :     
          variables corrélées transitivement :     
              
              
         Groupe  21  :  basé sur    N.Unip     
          variables corrélées directement    :     
          variables corrélées transitivement :     
              
              
         Groupe  22  :  basé sur    Q.Unip     
          variables corrélées directement    :   * N.Q     
          variables corrélées transitivement :     
              
              
         Groupe  23  :  basé sur    P.Unip     
          variables corrélées directement    :     
          variables corrélées transitivement :     
              
              
         Groupe  24  :  basé sur    H.Unip     
          variables corrélées directement    :     
          variables corrélées transitivement :     
              
              
         Groupe  25  :  basé sur    F.W.Y     
          variables corrélées directement    :   * C.F.Y.W     
          variables corrélées transitivement :     
              
              
         Groupe  26  :  basé sur    C.W     
          variables corrélées directement    :     
          variables corrélées transitivement :     
              
              
         Groupe  27  :  basé sur    R.E.S.P     
          variables corrélées directement    :     
          variables corrélées transitivement :     
              
              
              
         Résumé des dimensions     
          données initiales :    710    45     
          données finales   :    710    27     
              
              
    

    On remarquera que cette technique est plus efficace que la précédente pour l'exemple considéré car elle ne conserve que 27 variables au lieu de 29.

    Trouver le meilleur représentant par paquet n'est pas un problème simple non plus car il faut savoir qu'une variable "fortement explicative" lorsqu'on analyse tous les modèles à une seule variable ne sera pas forcément sélectionnée lorsqu'on passe en revue tous les modèles à deux, trois variables ou plus...

  13. La réponse est Rweb. Il s'agit d'une interface Web à R sous la forme d'un formulaire. En France, on peut par exemple utiliser pbil-rweb.

    En général, Rweb contient de nombreux packages. Vous pouvez par exemple essayer de copier/coller le code suivant pour le vérifier :

    
         ## récupération d'un tableau XHTML dans R
         
         # chargement du package XML
         
         library(XML)
         
         # chargement du package stringr
         
         library(stringr) # pour la fonction str_replace()
         
         # url de la page Web à utiliser
         
         url  <- "http://forge.info.univ-angers.fr/~gh/wstat/Programmation_R/progr.php?n=1&m=s"
         tabp <- readHTMLTable(url,which=3,stringsAsFactors=FALSE)
         print(tabp,right=FALSE)
         
         # un peu de "ménage"
         
         colnames(tabp) <- str_replace(colnames(tabp),"\\n","")
         
         # tout sauf les deux derniers caractères
         
         tsdc <- function(x) { substr(x,1,nchar(x)-2) }
         
         tabp[,2] <- as.numeric( tsdc(tabp[,2]) )
         print(tabp,right=FALSE)
         
         ## récupération d'une liste
         
         ip  <- "http://fr.wikipedia.org/wiki/Institut_Pasteur"
         cdr <- readHTMLList(ip,which=7)
         
         # conversion des accents
         
         iconv(cdr,from="UTF-8",to="LATIN1")
         print(cbind(cdr))
         
         
    
  14. Oui, Sweave est indispensable pour les rapports et les articles car c'est un gage de reproductibilité et de gain de temps. Après tout, il ne s'agit que d'inclure du R dans du code LaTeX. Ce n'est donc pas compliqué quand on connait LaTeX. Voici un extrait de code Sweave :

    
         \section{Introduction}     
              
         <<echo=FALSE,results=hide>>=     
              
         options(encoding = "latin1")     
         source("poursweave.r",encoding="latin1")     
              
         nlu <- 10      # nombre de lignes \ufffd lire     
         usr <- "INRA"  # pour montrer que c'est interactif     
         dos <- "iris"   # iris ou elf     
              
         nbl <- demoSw(dos,nlu,usr,1)     
              
         @     
              
         \section{Quelques lignes de donn\'{e}es du fichier : \Sexpr{dos} }     
              
         Le fichier elf contient \Sexpr{nbl} lignes.     
         L'utilisateur \Sexpr{usr} veut traiter les \Sexpr{nlu} premi\`{e}res lignes de ce fichier.     
              
    

    Comme on peut le voir, les fragments \Sexpr{...} correspondent à des valeurs que R insère dans le code LaTeX alors que les parties qui commencent par << et qui se terminent par @ sont du code R directement interprété.

  15. Oui, interfacer R et php est assez facile à réaliser car R a un mode batch. En d'autres termes, on peut au moins communiquer via des fichiers-texte.

    En voici un exemple, nommé aqt.

 

 

retour gH    Retour à la page principale de   (gH)