Objets et vecteurs

Pour l'instant, nous avons utilisé R pour faire la même chose que les calculatrices de nos ordinateurs et téléphones. Alors, c'est super, mais franchement pas passionnant. Avançons un peu.

Objets

Les objets sont globalement n'importe quoi (on pourrait presque les appeler "trucs") que l'on crée afin de stocker quelque chose (une ou plusieurs valeurs, mais aussi plein d'autres machins que nous verrons plus tard). Pour en créer un, on tape une ou des lettres, suivies de <- (chevron orienté vers l'objet et tiret), puis une valeur ou un calcul :

x <- 2

x
#[1] 2

x <- 46 + 2

x
#[1] 48

youpi <- 33 * 2

youpi
#[1] 66

Pour dupliquer un objet, on peut simplement le mettre dans un autre objet (en clair, stocker la valeur d'un objet dans un autre). Ça nous permet d'appliquer des calculs ou modifier la valeur de notre objet initial tout en conservant cet objet.

x <- 42

y <- x

y
#[1] 42

y <- y + 3

# oui, j'ai additionné un objet avec lui-même, c'est tout à fait faisable

y
#[1] 45 ==> y a une nouvelle valeur

x
#[1] 42 ==> x n'a pas été modifié

Règles de nommage

On est assez libres pour nommer nos objets, mais il y a tout de même quelques règles à respecter:

  • Ne pas commencer par un chiffre
  • Les seuls caractères spéciaux autorisés sont . et _.
  • Il faut respecter la casse (les majuscules, tout ça). Je conseille donc de les éviter de façon générale.

Vecteurs

Les objets que nous venons de voir ne contiennent qu'une seule valeur, c'est pas d'une utilité folle. Alors on peut créer plein d'objets que l'on peut utiliser :

a <- 1
b <- 3
c <- 6
d <- 2

a+b+c+d
#[1] 12

Ou même :

e <- a+b+c+d

e
#[1] 12

Mais considérons que nous mesurons des diamètres de lèvres d'amphores (on va dire Dressel 43261) en centimètres. Ça nous donne :

diam1 <- 34
diam2 <- 42
diam3 <- 38
diam4 <- 12

On peut faire la somme totale des diamètres (même si c'est un peu débile).

diam1 + diam2 + diam3 + diam4
#[1] 126

Si on veut la moyenne, sans utiliser de fonction spécifique, on additionne toutes nos valeurs et puis on divise par le nombre d'observations.

(diam1 + diam2 + diam3 + diam4)/2
#[1] 63

On va pas se mentir, c'est fastidieux. Il y a évidemment moyen de mettre plusieurs valeurs dans un objet et un objet composé d'une suite de valeurs est un vecteur.

Pour créer un vecteur, il faut ajouter quelques éléments lors de la création d'un objet, c(). Le c est pour combine. Pour l'utiliser :

diametres <- c(34.2,42.6,38.66,13.8)

diametres
#[1] 34.20 42.60 38.66 13.80

1 : Oui, je sais ça n'existe pas, on se calme les antiquisant.e.s et les protohistorien.ne.s ! Et moi, mon humour me convient :smirk_cat:

Opérations sur les vecteurs

Et maintenant, si on fait une opération sur un vecteur, que se passe-t-il ? Eh bien testons :

diametres/4
#[1]  8.550 10.650  9.665  3.450

L'opération (ici une division par 4), a été appliquée pour chaque élément de notre vecteur. C'est quelque chose qui peut être assez pratique, par exemple pour changer d'échelle :

# Nos diamètres sont en cm et nous allons les convertir en mm, donc les multiplier par 10

diametres*10
#[1] 342.0 426.0 386.6 138.0

Maintenant, on va tester le croisement de deux vecteurs, en divisant les hauteurs par les diamètres :

hauteurs <- c(98,95,87,102)

hauteurs / diametres
#[1] 2.865497 2.230047 2.250388 7.391304

Les éléments de chaque vecteur ont été divisés l'un par l'autre et un à un. En clair, le premier élément du premier vecteur a été divisé par le premier élément du deuxième vecteur, le deuxième élément du premier vecteur par le deuxième du deuxième vecteur, etc. Cela implique plusieurs choses, déjà, comment faire une opération globale sur un vecteur ? (genre, on veut la moyenne des éléments qui le composent). Ensuite, si chaque élément de chaque vecteur est associé un à un, c'est que leur position est importante (et indexée).

Modulo

Le modulo, c'est souvent peu considéré par les gens qui débutent en exploration de données en SHS, alors qu'il s'agit d'une fonction bien pratique. Le modulo donne le reste d'une division pour garder le résultat entier. Par exemple, le modulo de 5/2, c'est 1; on divise 5 par 2, mais comme le résultat doit être un entier, le calcul complet est 5/2 = 4/2+1 (puisque 4/2 c'est 2, donc un entier, on est bons !). Le signe du modulo dans R, c'est %%.

5 %% 2
#[1] 1

On va tester si nos hauteurs sont des nombres pairs :

hauteurs %% 2
#[1] 0 1 1 0

Seules la première et la dernière hauteur sont paires avec un modulo 2 = 0.

Position des éléments d'un vecteur

La position d'un élément est donnée par quelque chose que nous voyons depuis le début sans forcément comprendre à quoi il correspond. À chaque fois qu'un résultat est affiché, il y a un chiffre entre [] (crochets) qui apparaît. On va créer un vecteur un peu long et voir ce que ça donne :

x <- c(23,14,543,34,5,63,66,4,76,5,67,9,7,80,32,32,24,79,7,64,32,14,52,6,784,74,543,78)

x
#[1]  23  14 543  34   5  63  66   4  76   5  67   9   7  80  32  32  24  79   7  64  32  14
#[23]  52   6 784  74 543  78

On pourrait s'amuser à compter, mais je vous donne tout de suite la réponse, il s'agit de la position dans le vecteur du premier élément de la ligne. Ce même [], vous permet donc d'identifier une position. À l'inverse, si on tape le nom d'un vecteur suivi de [] (avec un numéro de position dedans), on peut obtenir directement la valeur située à cette position.

x[3]
#[1] 543

Et on peut tester si 52 est bien à la position 23 :

x[23]
#[1] 52

Il existe beaucoup de subtilités et de méthodes pour chercher et jouer sur les positions des valeurs, nous verrons cela plus tard, lors de nos traitements de données.

Les fonctions

On se demandait, un peu plus haut, comment appliquer des opérations à un vecteur dans son ensemble et pas valeur par valeur (genre, la moyenne de notre vecteur x). Pour ça, R est rempli de fonctions. Une fonction, globalement, c'est une commande qui fait plein de trucs avec des options. Dans R, sa forme est le nom de la fonction suivi des paramètres et options entre parenthèse. Les fonctions bénéficient de l'autocomplétion, dans RStudio, si vous en tapez les premières lettres, celles qui commencent pareil sont proposées. La première proposition est sélectionnée par défaut (mais vous pouvez déplacer la sélection avec les flèches du clavier) et hop, on tape sur entrée; la fonction sélectionnée est insérée avec ses parenthèses et le curseur est placé entre les parenthèses, il n'y a donc plus qu'à taper vos paramètres si vous en avez, sinon directement Entrée (enfin il faut très souvent au moins indiquer les données sur lesquelles appliquer la fonction). Quelques exemples de fonctions :

La valeur minimale :

min(x)
#[1] 4

La valeur maximale (oui, ce monde est fou):

max(x)
#[1] 784

La valeur la plus basse et la plus haute (Les deux précédentes commandes à la fois quoi) :

range(x)
#[1]   4 784

La moyenne (surprenant, non ?):

mean(x)
#[1] 100.6071

La médiane (bon, tout le monde distingue bien moyenne et médiane ?) :

median(x)
#[1] 33

La variance et l'écart-type (standard deviation en anglais)

var(x)
#[1] 36168.17

sd(x)
#[1] 190.1793

La somme totale des éléments du vecteur:

sum(x)
#[1] 2817

Les valeurs uniques:

unique(x)
#[1]  23  14 543  34   5  63  66   4  76  67   9   7  80  32  24  79  64  52   6 784  74  78

Le nombre de valeurs:

length(x)
#[1] 28

Le type d'objet et une description (vraiment) très rapide:

str(x)
# num [1:28] 23 14 543 34 5 63 66 4 76 5 ...

Là, on a plein de trucs bien pratiques (les noms sont explicites, je vous laisse deviner):

summary(x)
#   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
#   4.00   12.75   33.00  100.61   74.50  784.00

La différence entre chaque valeur successive :

diff(x)
#[1]   -9  529 -509  -29   58    3  -62   72  -71   62  -58   -2   73  -48    0   -8   55  -72
#[19]   57  -32  -18   38  -46  778 -710  469 -465

La somme cumulative, élément après élément :

cumsum(x)
#[1]   23   37  580  614  619  682  748  752  828  833  900  909  916  996 1028 1060 1084 1163
#[19] 1170 1234 1266 1280 1332 1338 2122 2196 2739 2817

Et, bien sûr, on peut imbriquer des fonctions :

length(unique(x))
#[1] 22

Il y a 22 valeurs uniques dans notre vecteur.

La fonction help

La fonction la plus importante est probablement help(). Je me doute bien que vous n'allez pas apprendre toutes les fonctions et leurs paramètres par cœur, c'est là que la fonction help vient vous sauver dans la nuit sombre de vos errances de tapage de commandes. Son utilisation est très simple, help(*nom de la commande sur laquelle vous avez besoin d'un petit coup de main*):

help(median)

La commande vous affiche l'explication de la commande dans RStudio avec une description de la commande, des paramètres, des valeurs liées, une petite citation bibliographique parce que c'est toujours bien et, pour finir, des exemples (vous avez vraiment tout là).

Alternativement, vous pouvez taper :

?median

qui fonctionne à peu près pareil.

Les arguments

Je n'ai pas développé dessus plus haut, mais les fonctions peuvent prendre plusieurs arguments qui sont séparés par des virgules, c'est par exemple de cette façon que nous avons utilisé c() en lui donnant plusieurs arguments.

La fonction help() nous donne l'ensemble des arguments possibles pour une fonction. Par exemple :

help(mean)

Nous retourne :

mean(x, ...)

Default S3 method:

mean(x, trim = 0, na.rm = FALSE, ...)

Ici, trois arguments indiqués (même si plus sont disponibles). x indique les données, les arguments moins évidents sont explicités en plus bas dans l'aide (même x d'ailleurs). Un argument est donné sous la forme argument =. L'ordre indiqué dans l'aide est celui par défaut. Soit vous indiquez vos arguments dans l'ordre et vous n'avez pas besoin de les nommer, soit vous devez les indiquer avec argument =.

Générer des suites de valeurs

Dans certains cas, il peut être utile de générer des suites de nombres, en créant des données ou même en les interrogeant (on verra tout ça un peu plus dans les pages suivantes).

Les : vont générer une suite incrémentée de 1, depuis la valeur qui précède les : à celle qui leur succède :

x <- 1:28

Pour contrôler un peu plus la génération des suites, la fonction seq() est très pratique dans son usage basique, seq(min, max, pas) :

seq(2,35,4)
#[1]  2  6 10 14 18 22 26 30 34
#La plus haute valeur est 34 car par pas de 4, on ne pouvait pas tomber pile sur 35 et que cette valeur ne peut pas non plus être dépassée.

Un type de génération que j'aime bien, c'est celle qui crée des distributions normales aléatoires. Il s'agit de rnorm(nombre de valeurs, moyenne, écart-type) :

rnorm(60,14,10)
# [1]   1.3233514  -4.6967920  16.5148504  14.7976726  16.7438506   5.4070413
# [7]   9.8316416  29.1486864  11.6293148  27.2316077  10.0895463   9.7892557
# Bon là, je n'ai mis que les deux premières lignes, 60 valeurs quand même...

Il existe évidemment plein d'autres types de générateurs de suites de plein de types différents, je vous laisse explorer.

Les principaux types de données

Pour l'instant, nous n'avons joué qu'avec des chiffres, or, R (imprononçable ce truc) peut utiliser trois principaux types de données : numériques, textuelles et logiques. Les fonctions str() ou class() peuvent nous indiquer le type de données qui compose un objet.

Données numériques

Je ne vais pas revenir dessus, ce sont des nombres entiers ou réels, seule précision, R distingue entier et réels.

x <- seq(3,68,8)

str(x)
#num [1:9] 3 11 19 27 35 43 51 59 67

class(x)
#[1] "numeric"

Pour forcer le type entier ("integer"), il faut rajouter un L.

x <- c(3L,5L,2L,6L)
class(x)

#[1] "integer"

Données textuelles

Ce sont des chaînes de caractères, donc du texte. Pour utiliser du texte, il faut le placer entre guillemets ".

x <- c("chat", "chien", "tortue", "souris")

x
#[1] "chat"   "chien"  "tortue" "souris"

class(x)
#[1] "character"

Données logiques

Ce sont des booléens de type OUI/NON, PRÉSENT/ABSENT, VRAI/FAUX, etc. Dans R, ces données prennent les formes TRUE et FALSE (tout en majuscule). Pour l'instant, ça ne vous paraît peut-être pas très intéressant de prime abord, mais je vous assure que pour pas mal de traitements de données, c'est vite très puissant (on commencera à voir ça avec les tests conditionnels).

x <- c(TRUE,FALSE,FALSE,FALSE,TRUE,TRUE) 

class(x)
#[1] "logical"

D'ailleurs un truc bien pratique, c'est qu'on peut facilement compter les TRUE. Si vous avez vu des tableaux de données un peu anciens, on a souvent l'habitude de coder la présence/absence en 1,0. En réalité, c'est un peu ce système qui est utilisé dans R, avec les TRUE qui valent 1 et les FALSE qui valent 0. Donc on peut, par exemple, compter le nombre de positifs de notre vecteur x avec la fonction sum() :

sum(x)
#[1] 3

Types de vecteurs

Il faut garder à l'esprit qu'un vecteur ne peut être que d'un type. Si vous mélangez des types en créant un vecteur, vous verrez que la fonction class() ne retourne qu'un seul argument. Une idée à considérer, c'est qu'en mélangeant des types, le vecteur prendra le type le plus complexe (complexité : logique < numérique < texte) :

Types de données en entrée Type de vecteur en sortie
Logique + numérique numérique
Logique + texte texte
numérique + texte texte
Logique + numérique + texte texte

Et démontration dans R :

x <- c(TRUE,2)
class(x)
#[1] "numeric"

Oui, TRUE est converti en 1 et FALSE en 0. C'est logique avec ce qu'on a vu juste avant.

x <- c(TRUE,"chat")
class(x)
#[1] "character"

Si on regarde notre vecteur, TRUE est maintenant indiqué "TRUE", c'est donc bien du texte.

x <- c(2,"chat")
class(x)
#[1] "character"

Comme pour le précédent exemple, 2 est maintenant affiché "2".

x <- c(2,"chat","TRUE")
class(x)
#[1] "character"

Plus que du texte, c'est un peu triste, non ? :crying_cat_face:

Les listes

Un vecteur ne peut être que d'un type, mais il peut arriver (très rarement dans les analyses statistiques, mais ça peut arriver dans le nettoyage et la gestion de données) de vouloir utiliser un genre de vecteur qui possède plusieurs types de données. Il existe un type d'objet dans ce cas, la liste, associée à la fonction list() :

x <- list(2,"chat","TRUE")
class(x)
#[1] "list"

Et si vous l'observez, avec la fonction View() par exemple, vous verrez que chaque valeur a conservé son type.

Les valeurs manquantes

Nous traitons toutes et tous des données parfois un peu lacunaires pour plein de raisons, données anciennes, origines multiples, changements de direction, projets un peu en bazar, trop de pluie ou de moustiques sur le terrain, inondation dans la réserve, enfin plein de trucs qui vous évoqueront probablement des souvenirs... Ces aléas aboutissent à des données dans lesquelles certaines valeurs sont manquantes. Dans R, les valeurs manquantes sont indiquées "NA", pour les bases SQL, elles sont "null" (NULL existe aussi dans R, mais on ne va pas l'aborder maintenant), enfin en fonction des logiciels ou des environnements, elles sont indiquées de façon différente.

Nous allons concrètement voir ce que donne la présence de données manquantes dans un vecteur :

x <- c(3,56,84,34,NA,42)

class(x)
#[1] "numeric"
#Même avec un NA, R identifie ce vecteur comme numérique

length(x)
#[1] 6
#Le NA est bien compté dans le nombre de valeurs

mean(x)
#[1] NA

La présence d'un NA rend l'opération impossible, il s'agirait de diviser 5 valeurs (les présentes) par 6 (le nombre de valeurs).

Un moyen de contourner ce problème, ajouter une option pour dire à R qu'il peut omettre les NA, na.rm = TRUE :

mean(x, na.rm=TRUE)
#[1] 43.8

Les opérateurs logiques

Les opérateurs logiques peuvent sembler un peu relous, a priori, mais je vous assure que dès que vous commencerez à automatiser des choses (oui, oui, vous le ferez bien un jour !), c'est fort utile. Les opérateurs logiques, comme vous pouvez vous en douter, retournent un vecteur logique. L'idée est de comparer des vecteurs et le résultat qui nous est retourné prend la forme d'un vecteur logique.

Les principaux opérateurs logiques :

Opérateur Signification
== égal à
!= différent de
> strictement supérieur à
>= supérieur ou égal à
< strictement inférieur à
<= inférieur ou égal à
Association d'arguments
\ union (OU)
\ \ OU (sur un argument de longueur 1)
& intersect (ET)
&& ET (sur un argument de longueur 1)
! inversion

La principale différence entre & / && et | / || est que le double caractère fonctionne sur un argument unique et correspond à des caractères de programmation standard, d'où le fait qu'on le retrouve très souvent utilisé. Sur des vecteurs, on aura tendance à utiliser les caractères simples, mais cela demande un peu de pratique (sauf si vous avez l'habitude du SQL ou ce genre de pratiques et là, ça devrait le faire).

Quelques exemples :

x <- c(1,2,3,5,7,8,9)
y <- c(3,2,4,6,6,8,3)

y == 6
#[1] FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE

x == y
#[1] FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE

x != y
#[1]  TRUE FALSE  TRUE  TRUE  TRUE FALSE  TRUE

y < x
#[1] FALSE FALSE FALSE FALSE  TRUE FALSE  TRUE

x <= y
#[1]  TRUE  TRUE  TRUE  TRUE FALSE  TRUE FALSE

x == y | y < x
#[1] FALSE  TRUE FALSE FALSE  TRUE  TRUE  TRUE

x == y & y < x
#[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE
powered by GitbookLes ateliers du MIAOU 22-12-2025 11:53:32

results matching ""

    No results matching ""