.. include:: weblinks.txt .. _vectors: Vecteurs ======== R manipule deux types de structures de données: - les structures de données de base - les structures de données composites La structure de base la plus simple est le vecteur et nous allons étudier son fonctionnement dans ce chapitre. Pour stocker des données hétérogènes et complexes, on a besoin de structures de données composites, plus évoluées. La ``data.frame`` en fait partie. On étudiera son fonctionnement dans le chapitre :ref:`dataframes`. Définition ---------- Un vecteur est une entité consistant en une collection ordonnée d'éléments atomiques. Par élément atomique, on entend : ============ ============================================================== Atomic Types Data ============ ============================================================== numeric Numeric data (approximations of the real numbers) integer Integer data (whole numbers). integer is a subclass of numeric complex Complex numbers logical Boolean character Character data (strings) raw Binary data ============ ============================================================== Dans le langage R, les vecteurs: - sont homogènes (ne stockent que des données de même type) - sont indexables (on peut récupérer un ou plusieurs éléments à partir de leur position) - peuvent avoir des éléments nommés Pour construire un vecteur ``x`` contenant 5 éléments (10.4, 5.6, 3.1, 6.4 et 21.7), on utilise la commande suivante:: > x <- c(10.4, 5.6, 3.1, 6.4, 21.7) > x [1] 10.4 5.6 3.1 6.4 21.7 C'est une instruction d'affectation pour laquelle on retrouve: - à gauche : le nom de la variable - à droite : la fonction :func:`c` prenant un nombre arbitraire d'arguments et retournant un vecteur dont les éléments sont obtenus par concaténation de ses arguments. Notons que les vecteurs ont une structure "plate", indépendamment de l'instruction de construction:: > x <- c(10.4, c(5.6, 3.1, c(6.4, 21.7))) > x [1] 10.4 5.6 3.1 6.4 21.7 .. warning:: Les affectations peuvent également utiliser la fonction :func:`assign` mais son utilisation n'est pas encouragée pour des raisons évidentes de simplicité d'écriture:: > assign("x", c(10.4, 5.6, 3.1, 6.4, 21.7)) L'opérateur ``<-`` peut être vu comme un raccourci syntaxique et sera utilisé de façon préférentielle. Considérons l'affectation suivante:: > y <- c(x, 0, x) > y [1] 10.4 5.6 3.1 6.4 21.7 0.0 10.4 5.6 3.1 6.4 21.7 Un vecteur ``y`` est créé en concaténant les arguments de la fonction :func:`c` dans l'ordre d'apparition. Il est possible d'insérer une ou plusieurs valeurs dans un vecteur avec la fonction :func:`append`:: > append(x,99) [1] 10.4 5.6 3.1 6.4 21.7 99.0 > append(x,99,3) # third argument describe position where values will be inserted [1] 10.4 5.6 3.1 99.0 6.4 21.7 > append(x,c(99,100),3) # multiple values insertion [1] 10.4 5.6 3.1 99.0 100.0 6.4 21.7 Arithmétique des vecteurs ------------------------- Voici quelques règles qui régissent le comportement des vecteurs: - lorsque des vecteurs sont utilisés dans une expression arithmétique, les opérations sont effectuées **élément par élément** - les vecteurs n'ont pas besoin d'avoir une longueur identique, un processus de **recyclage** de données permet de construire un vecteur résultat de taille la plus grande taille des vecteurs mis en jeu. En particulier une constante sera transformé en un vecteur par répétition de sa valeur. .. admonition:: Question Essayer de prédire le résultat de ``v <- 2*x + y + 1`` en répondant préalablement aux questions suivantes: - quelle est la longueur de ``x`` ? - quelle est la longueur de ``y`` ? - quelle est la longueur de ``1`` ? - quel est le vecteur le plus long ? - imaginer la règle de recyclage du vecteur le plus court Utiliser la console R pour vérifier En utilisant les vecteurs précédents, le résultat devrait être:: > v <- 2*x + y + 1 Warning message: In 2 * x + y : longer object length is not a multiple of shorter object length > v [1] 32.2 17.8 10.3 20.2 66.1 21.8 22.6 12.8 16.9 50.8 43.5 R construit un nouveau vecteur ``v`` : - de longueur 11, la longueur de ``y`` le plus long vecteur mis en jeu - recycle les valeurs de ``x`` jusqu'à obtenir un vecteur de longueur 11 : 10.4 5.6 3.1 6.4 21.7 (+) 10.4 5.6 3.1 6.4 21.7 (+) 10.4 - recycle la valeur ``2`` jusqu'à obtenir un vecteur de longueur 11 : 2 2 2 2 2 2 2 2 2 2 2 - recycle la valeur ``1`` jusqu'à obtenir un vecteur de longueur 11 : 1 1 1 1 1 1 1 1 1 1 1 - effectue l'arithmétique élément par élément .. admonition:: Question Quel est le sens du warning affiché dans la console lors de la construction de ``v`` ? .. Because ``y`` length is not a multiple of ``x`` length, a warning message is printed to the console. Les opérateurs arithmétiques sont : - ``+`` - ``-`` - ``*`` - ``/`` - ``^`` (exponentiation) Les opérations mathématiques courantes: - :func:`log` - :func:`exp` - :func:`sin` - :func:`cos` - :func:`tan` - :func:`sqrt` - ... Les fonctions :func:`max` et :func:`min` retournent la plus grande et la plus petite valeur du vecteur passé en argument sous la forme d'un vecteur de taille ``1`` (il n'y a pas de scalaire en R):: > v [1] 32.2 17.8 10.3 20.2 66.1 21.8 22.6 12.8 16.9 50.8 43.5 > max(v) [1] 66.1 > min(v) [1] 10.3 La fonction :func:`range` utilise les fonctions :func:`min` et :func:`max` pour construire le résultat:: > range(v) [1] 10.3 66.1 La fonction :func:`length` retourne le nombre d'éléments:: > length(v) [1] 11 La fonction :func:`sum` fait ce qu'elle doit faire:: > sum(v) [1] 315 et la fonction :func:`prod` également:: > prod(v) [1] 1.856438e+15 On a vu précédemment que la fonction :func:`summary` produisait des statistiques de premier ordre. La moyenne est obtenue avec :func:`mean` et la variance avec :func:`var`:: > mean(v) [1] 28.63636 > var(v) [1] 312.4905 La fonction :func:`sort` retourne une permutation du vecteur passé en argument, avec les éléments ordonnés dans le sens croissant:: > v [1] 32.2 17.8 10.3 20.2 66.1 21.8 22.6 12.8 16.9 50.8 43.5 > sort(v) [1] 10.3 12.8 16.9 17.8 20.2 21.8 22.6 32.2 43.5 50.8 66.1 .. tip:: La plupart du temps le tri sera effectué sur une partie d'une data frame avec les fonctions du package ``dplyr``. Si le besoin de trier de simples vecteurs se fait sentir, la fonction :func:`sort` dispose de plusieurs arguments explicités dans la `documentation `_. Et d'autres fonctions sont également disponibles : :func:`order`, :func:`sort.list`, ... Les fonctions :func:`max` et :func:`min` fonctionnent également avec plusieurs arguments. Construisons 2 vecteurs constitués de valeurs aléatoires. On utilise pour celà la fonction :func:`sample` :: > a <- sample(1:100, 10, replace=FALSE) > a [1] 3 33 11 80 68 58 15 50 4 99 > b <- sample(1:100, 20, replace=FALSE) > b [1] 99 88 91 28 63 100 13 95 4 32 Sans surprise :: > min(a,b) [1] 3 > max(a,b) [1] 100 Les fonctions :func:`pmax` (parallel max) and :func:`pmin` (parallel min) retourne un vecteur de longueur la taille du plus long argument, constitué pour chaque position, de la valeur max ou min prise élément par élément. .. admonition:: Question Essayer de prédire le résultat retourné par :func:`pmax` et :func:`pmin` lorsque ces fonctions sont appliquées aux vecteurs ``a`` et ``b``. Utiliser la console de R pour vérifier... .. > a [1] 3 33 11 80 68 58 15 50 4 99 > b [1] 99 88 91 28 63 100 13 95 4 32 > pmin(a,b) [1] 3 33 11 28 63 58 13 50 4 32 > pmax(a,b) [1] 99 88 91 80 68 100 15 95 4 99 .. _generating-regular-sequences: Génération de séquences ----------------------- La plupart du temps on travaille avec des jeux de données importés mais il est parfois nécessaire de compléter ces données en produisant des vecteurs de taille arbitraire. R dispose de plusieurs mécanismes pour "fabriquer" des données. L'opérateur ``:`` ................. On a déjà rencontré cet opérateur en début de chapitre. ``1:10`` est l'équivalent de ``c(1, 2, ..., 10)``:: > 1:10 [1] 1 2 3 4 5 6 7 8 9 10 L'opérateur ``:`` a une priorité plus grande que les opérateurs arithmétiques:: > 2*1:10 [1] 2 4 6 8 10 12 14 16 18 20 .. admonition:: Question Essayer de prédire le résultat des deux séquences ci dessous:: > n <- 10 > 1:n-1 > 1:(n-1) Vérifier dans la console... La construction ``10:1`` est utilisé pour générer une séquence dans l'ordre décroissant:: > 10:1 [1] 10 9 8 7 6 5 4 3 2 1 La fonction :func:`seq` ....................... La fonction :func:`seq` peut également être utilisée. Elle comporte 5 arguments, dont certains sont optionnels. Lorsqu'on l'utilise avec seulement deux arguments, elle se comporte comme l'opérateur ``:``: .. code-block:: r > seq(2,10) [1] 2 3 4 5 6 7 8 9 10 On peut également passer les informations avec des arguments nommés:: > seq(1,10) [1] 1 2 3 4 5 6 7 8 9 10 > seq(from=1, to=10) [1] 1 2 3 4 5 6 7 8 9 10 > seq(to=10, from=1) [1] 1 2 3 4 5 6 7 8 9 10 Les arguments optionnels ``by=value`` et ``length=value`` permettent de spécifier le pas et la longueur de la séquence. Si aucun n'est fourni la valeur par défaut ``by=1`` est utilisée:: > seq(-1, 1, by=.3) [1] -1.0 -0.7 -0.4 -0.1 0.2 0.5 0.8 > seq(length=9, from=-5, by=.2) [1] -5.0 -4.8 -4.6 -4.4 -4.2 -4.0 -3.8 -3.6 -3.4 Le cinquième argument ``along=vector`` est utilisé pour construire une séquence de longueur la longueur du vecteur passé en argument:: > seq(3, along=c("a", "b", "c", "d", "e")) [1] 3 4 5 6 7 La fonction :func:`rep` ....................... La fonction :func:`rep` est utilisé pour dupliquer des données. Dans sa forme la plus simple:: > x <- c(10.4, 5.6, 3.1, 6.4, 21.7) > rep(x, times=2) [1] 10.4 5.6 3.1 6.4 21.7 10.4 5.6 3.1 6.4 21.7 Une autre façon de l'utiliser:: > rep(x, each=2) [1] 10.4 10.4 5.6 5.6 3.1 3.1 6.4 6.4 21.7 21.7 Vecteurs logiques ----------------- On a beaucoup travaillé jusqu'à présent avec des grandeurs numériques mais R permet également de manipuler des vecteurs logiques. Les valeurs utilisées sont ``TRUE``, ``FALSE``, et ``NA``. Les deux premières sont souvent abrégées par ``T`` et ``F``. .. warning:: ``T`` et ``F`` sont de simples variables initialisées à ``TRUE`` et ``FALSE`` et peuvent être écrasées par l'utilisateur. La rigueur imposerait de toujours travailler avec ``TRUE`` et ``FALSE`` qui sont des variables réservées par le système. Pour illustrer le fonctionnement des vecteurs logiques, utilisons le vecteur ``x`` créé précédemment:: > x [1] 10.4 5.6 3.1 6.4 21.7 .. admonition:: Question Essayer de prédire le résultat de l'expression ``x > 6`` en inférant la longueur du vecteur résultat et en se souvenant que R travaille élément par élément. .. > x > 6 [1] TRUE FALSE FALSE TRUE TRUE .. ``x > 6`` is a vector of the same length as x with values ``FALSE`` corresponding to elements of x where the condition is not met and ``TRUE`` where it is. Les opérateurs logiques sont: - ``<`` - ``<=`` - ``>`` - ``>=`` - ``==`` (égalité exacte) - ``!=`` (inégalité) Si ``c1`` et ``c2`` sont des expressions logiques: - ``c1 & c2`` exprime le ET logique - ``c1 | c2`` exprime le OU logique - ``!c1`` exprime la négation .. important:: Si les vecteurs logiques sont impliqués dans des expressions arithmétiques, les valeurs logiques ``TRUE`` et ``FALSE`` sont forcées à ``1`` et ``0`` Valeurs manquantes ------------------ Comme au l'a vu dans le paragraphe :ref:`special-numbers`, il peut y avoir des éléments manquants dans un vecteur identifiés par le nombre spécial ``NA``. En général, toute opération impliquant un ``NA`` retourne un ``NA``. La fonction :func:`is.na` retourne un vecteur logique de même taille que celui passé en paramètre et comportant la valeur ``TRUE`` si l'élément correspondant est ``NA``:: > z <- c(1:3,NA) > z [1] 1 2 3 NA > is.na(z) [1] FALSE FALSE FALSE TRUE La fonction :func:`is.na` retourne ``TRUE`` pour les valeurs ``NA`` et ``NaN``. La fonction :func:`is.nan` retourne ``TRUE`` pour les seules valeurs ``NaN``:: > z <- append(z, NaN) > z [1] 1 2 3 NA NaN > is.na(z) [1] FALSE FALSE FALSE TRUE TRUE > is.nan(z) [1] FALSE FALSE FALSE FALSE TRUE .. important:: Lorsqu'on travaille avec des jeux de données réélles, il est de première importance d'identifier les observations complètes (ne comportant aucun ``NA``) et les observations incomplètes (comportant au moins un ``NA``). Vecteurs de caractères ---------------------- Les chaines de caractères se définissent avec la double ``"`` ou simple apostrophe ``'``. Un vecteur de chaines de caractères est une séquence ordonnée de chaines de caractères. A titre d'exemple, la fonction :func:`names` appliquée à la ``data.frame`` contenant les informations sur les véhicules utilisée dans le chapitre :ref:`overview` retourne un tel vecteur:: > names(veh) [1] "lib_mrq" "lib_mod_doss" "lib_mod" [4] "dscom" "cnit" "tvv" [7] "cod_cbr" "hybride" "puiss_admin_98" [10] "puiss_max" "typ_boite" "nb_rapp" [13] "conso_urb" "conso_exurb" "conso_mixte" [16] "co2" "co_typ_1" "hc" [19] "nox" "hcnox" "ptcl" [22] "masse_ordma_min" "masse_ordma_max" "champ_v9" [25] "date_maj" "Carrosserie" "gamme" Le caractère ``\`` est utilisé comme caractère d'échappement. Ainsi: - ``\\`` est affiché ``\`` - pour afficher le caractère ``"``, la chaine de caractère sera ``\"`` - ``\n`` sera utilisé pour un retour à la ligne - ``\t`` pour une tabulation - etc... On construit un vecteur de caractères comme un vecteur numérique avec la fonction :func:`c`:: > x <- c("a", "b", "c") > x [1] "a" "b" "c" La fonction :func:`paste`, à laquelle on peut passer un nombre arbitraire d'arguments, permet la concaténation:: > paste("a", "b", "c") [1] "a b c" Si les arguments ne sont pas des chaines de caractère, R tente de les forcer:: > paste("a", "b", 1) [1] "a b 1" > paste("a", "b", FALSE) [1] "a b FALSE" Par défaut l'espace simple est utilisé comme séparateur, mais il est paramétrable:: > paste("a", "b", "c", sep="") [1] "abc" :func:`paste` peut également prendre des vecteurs en argument, et procéder à la concaténation élément par élément:: > x <- c("a", "b", "c") > y <- c("d", "e", "f") > paste(x, y, sep="") [1] "ad" "be" "cf" .. admonition:: Question En utilisant la règle de recyclage, essayer de prédire le résultat des 2 instructions suivantes:: > paste(c("X","Y"), 1:8, sep="") > paste(c("X","Y"), 1:5, c("a", "b"), sep="-") Vérifier dans la console .. result : [1] "X1" "Y2" "X3" "Y4" "X5" "Y6" "X7" "Y8" [1] "X-1-a" "Y-2-b" "X-3-a" "Y-4-b" "X-5-a" Vecteurs d'index ---------------- On peut sélectionner une partie d'un vecteur avec l'opérateur d'indexation ``[ ]``. Sélection par condition logique ............................... On peut passer un vecteur logique à l'opérateur d'indexation. Dans ce cas, les éléments sélectionnés sont ceux pour lesquelles l'élément du vecteur d'indexation prend la valeur ``TRUE``. Ceux correspondant à la valeur ``FALSE`` sont écartés. Par exemple: .. code-block:: r > x <- c(100,34,NA,78,6,NA,84,NA,27,59) > is.na(x) [1] FALSE FALSE TRUE FALSE FALSE TRUE FALSE TRUE FALSE FALSE > !is.na(x) [1] TRUE TRUE FALSE TRUE TRUE FALSE TRUE FALSE TRUE TRUE > x[is.na(x)] [1] NA NA NA > x[!is.na(x)] [1] 100 34 78 6 84 27 59 C'est une façon de filtrer les valeur manquantes/non manquantes d'un vecteur. .. tip:: - on peut construire des vecteur logiques complexes avec les opérateurs ``&`` et ``|`` - on disposera de fonction de plus haut niveau lorsqu'il s'agira de travailler sur une ``data.frame`` .. admonition:: Question Essayer de prédire le résultat de l'instruction suivante: .. code-block:: r > (x+1)[(!is.na(x)) & x>40] Vérifier dans la console .. result : [1] 101 79 85 60 Quels indices sont TRUE ? ......................... La fonction :func:`which` est utile pour identifier les indices ``TRUE`` en fonction d'un prédicat passé en argument:: > which(is.na(x)) [1] 3 6 8 > which(x>40) [1] 1 4 7 10 Sélection par index ................... Dans ce cas les valeurs du vecteur passé à l'opérateur d'indexation doivent être dans l'ensemble ``{1, 2, …, length(x)}``. Les éléments correspondants sont sélectionnés et concaténés, dans cet ordre, pour construire le résultat. Le vecteur d'index peut être de longueur arbitraire:: > x [1] 100 34 NA 78 6 NA 84 NA 27 59 > x[3] [1] NA > x[1:5] [1] 100 34 NA 78 6 .. admonition:: Question Essayer de prédire le résultat de l'instruction suivante:: > x[c(5,4,3)] Vérifier dans la console .. result : [1] 6 78 NA Désélection par index ..................... Le signe ``-`` est utilisé pour identifier les valeurs à exclure:: > x[-(1:5)] [1] NA 84 NA 27 59 .. admonition:: Question Essayer de prédire le résultat de l'instruction suivante:: > x[-c(5,4,3)] Vérifier dans la console .. result : [1] 100 34 NA 84 NA 27 59 Sélection par nom ................. Lorsqu'un objet posséde un attribut name pour identifier ses composants, on peut utiliser un vecteur de chaines de caractères pour sélectionner des éléments:: > fruit <- c(5, 10, 1, 20) > names(fruit) NULL > names(fruit) <- c("orange", "banana", "apple", "peach") > fruit[c("apple","orange")] apple orange 1 5 Il est plus lisible et maintenable de sélectionner des éléments par nom, plutôt que par indice. On retrouvera cette façon de faire lorsqu'on manipulera des ``data.frame`` dans le chapitre :ref:`dataframes`. Affectation ........... On peut utiliser l'opérateur d'indexation à gauche de l'opérateur d'affectation (LHS) pour affecter des valeurs à une sous partie d'un vecteur. L'expression doit être de la forme ``vector[index_vector]``. Par exemple, on remplace les valeurs manquantes par un 0:: > x[is.na(x)] <- 0 > x [1] 100 34 0 78 6 0 84 0 27 59 Une façon (tordue) de prendre la valeur absolue:: > y[y < 0] <- -y[y < 0] Cet exemple n'est qu'une illustration de l'utilisation de l'indexation, et on choisira évidemment la forme classique:: > y <- abs(y) Coercition ---------- R permet la coercition explicite ou implicite entre les objets. **La coercition explicite** est effectuée avec la famille de fonctions :func:`as.xxx`:: > a <- -1:1 > a [1] -1 0 1 > typeof(a) [1] "integer" La règle est que la coercition s'applique du type le plus contraint vers le type le moins contraint, c'est à dire dans l'ordre : logical, integer, double, et character. Certaines opérations sont évidentes:: > as.character(a) [1] "-1" "0" "1" > as.complex(a) [1] -1+0i 0+0i 1+0i :func:`as.numeric` force l'objet vers un type ``double``:: > as.numeric(a) [1] -1 0 1 > typeof(as.numeric(a)) [1] "double" Attention aux comparaisons, ``==`` teste l'égalité, indépendamment du type:: > a == as.numeric(a) [1] TRUE TRUE TRUE alors que la fonction :func:`identical` compare également le type:: > identical(a,as.numeric(a) ) [1] FALSE Lors de la conversion vers le type logique, seules les valeurs nulles sont ``FALSE`` :: > as.logical(a) [1] TRUE FALSE TRUE Si la coercition n'a pas de sens, l'opération échoue:: > as.numeric(c("a", "b")) [1] NA NA Warning message: NAs introduced by coercion **La coercition implicite** est mise en oeuvre lorsqu'on manipule des éléments inhomogènes:: > a<-c(1,"a") > typeof(a) [1] "character" > a [1] "1" "a" > a<-c(FALSE, "a") > typeof(a) [1] "character" > a [1] "FALSE" "a" > a<-c(1, TRUE) > typeof(a) [1] "double" > a [1] 1 1 La coercition implicite n'est pas souhaitable pour des questions de lisibilité et de maintenance:: > as.numeric("1") < 2 [1] TRUE est meilleur que:: > "1" < 2 [1] TRUE Exercices --------- Définir les vecteurs ``x`` et ``y`` comme suit:: > x<-c(4,2,6) > y<-c(1,0,-1) .. admonition:: Question Essayer de prédire le résultat des instructions suivantes:: > length(x) > sum(x) > sum(x^2) > x+y > x*y > x-2 > x^2 Vérifier dans la console .. admonition:: Question Essayer de prédire le résultat des instructions suivantes:: > 7:11 > seq(2,9) > seq(4,10,by=2) > seq(3,30,length=10) > seq(6,-4,by=-2) Vérifier dans la console .. admonition:: Question Essayer de prédire le résultat des instructions suivantes:: > rep(2,4) > rep(c(1,2),4) > rep(c(1,2),c(4,4)) > rep(1:4,4) > rep(1:4,rep(3,4)) Vérifier dans la console .. admonition:: Question Use the rep function to define simply the following vectors in R:: [1] 6 6 6 6 6 6 [1] 5 8 5 8 5 8 5 8 [1] 5 5 5 5 8 8 8 8 Considérons maintenant l'instruction suivante:: x <- c(5,9,2,3,4,6,7,0,8,12,2,9) .. admonition:: Question Essayer de prédire le résultat des indexations suivantes:: > x[2] > x[2:4] > x[c(2,3,6)] > x[c(1:5,10:12)] > x[-(10:12)] Vérifier dans la console .. _vectors-application: Application : population urbaine -------------------------------- Cet exercice d'application utilise un jeu de données sur la population des principales villes françaises entre 1962 et 2012. Créer l'environnement de travail ................................ #. Démarrer R Studio #. S'assurer qu'aucun projet n'est ouvert, sinon :command:`R Studio > File > Close Project` #. Créer un nouveau projet "Population" :command:`R Studio > File > New project... > New Directory > New Project` Le jeu de données concernant la population des 20 plus grandes villes de France entre 1962 et 2012 est stocké au format :file:`.RData`. Enregistrer ce :download:`fichier ` dans le répertoire du projet. .. hint:: Immédiatement après la création du projet, le répertoire doit contenir un dossier masqué et deux fichiers, dont le fichier :file:`.RData` téléchargé ci dessus.. .. image:: images/06-vectors-application.png :width: 600px :align: center Pour extraire les données vers l'espace de travail, cliquer sur le nom du fichier dans le navigateur de fichiers de R Studio. Plusieurs vecteurs doivent apparaître dans l'explorateur d'objets. Exploration ........... On va manipuler ces différents vecteurs pour explorer l'évolution de la population française, dans quelques unes des plus grandes villes, entre 1962 et 2012. A l'aide de la console R, répondre aux questions suivantes : - Combien de villes sont représentées dans les données ? Lesquelles ? .. length(cities) ; cities - Combien d'années sont représentées dans les données ? Lesquelles ? .. length(years) ; years - En quelle année Angers a t-elle dépassé pour la première fois 150.000 habitants ? .. > angers > 150000 [1] FALSE FALSE FALSE FALSE FALSE TRUE TRUE FALSE > years[angers > 150000] [1] 1999 2007 years[angers > 150000][1] [1] 1999 - Quelle est la population moyenne de Bordeaux sur les 3 derniers recensements ? .. > bordeaux [1] 278403 266662 223131 208159 210336 215363 235178 241287 > tail(bordeaux, 3) [1] 215363 235178 241287 mean(tail(bordeaux, 3)) [1] 230609.3 - Calculer l'évolution de la population parisienne à chacun des recensements ? Utiliser la fonction :func:`diff`. Commenter la taille et la composition du vecteur obtenu. .. > paris [1] 2790091 2590771 2299830 2176243 2152423 2125246 2193030 2240621 > length(paris) [1] 8 > diff(paris) [1] -199320 -290941 -123587 -23820 -27177 67784 47591 > length(diff(paris)) [1] 7 - Quelles sont les années pour lesquelles l'évolution de population a suivi la même pente (positive ou négative) à Lyon et Toulouse ? La fonction :func:`sign` peut être utile. .. > lyon [1] 535746 527800 456716 413095 415487 445452 472330 496343 > diff(lyon) [1] -7946 -71084 -43621 2392 29965 26878 24013 > sign(diff(lyon)) [1] -1 -1 -1 1 1 1 1 > toulouse [1] 323724 370796 373796 347995 358688 390350 439453 453317 > diff(toulouse) [1] 47072 3000 -25801 10693 31662 49103 13864 > sign(diff(toulouse)) [1] 1 1 -1 1 1 1 1 > sign(diff(lyon)) == sign(diff(toulouse)) [1] FALSE FALSE TRUE TRUE TRUE TRUE TRUE > years[sign(diff(lyon)) == sign(diff(toulouse))] [1] 1975 1982 1990 1999 2007