
Syntaxe R vs Python : guide côte à côte
Les mêmes briques de base dans les deux langages — et les deux différences qui piègent tout le monde
Une comparaison pratique, côte à côte, de la syntaxe R et Python pour quiconque maîtrise un langage et apprend l’autre : affectation de variables, types de données, vecteurs/listes, le piège de l’indexation à base 1 vs à base 0, opérateurs, if/else, boucles, fonctions, packages, chaînes de caractères et valeurs manquantes (NA vs None/NaN) — avec un tableau de correspondance R-vers-Python et un honnête « lequel utiliser quand ».
- Les deux différences qui piègent tout passant de R à Python (et inversement) — saisissez-les et le reste n’est que vocabulaire.
- Un tableau de correspondance : chaque construction de base en R à côté de son jumeau Python.
- Les briques de base côte à côte — affectation, types, vecteurs/listes, indexation, opérateurs,
if/else, boucles, fonctions, packages, chaînes de caractères, valeurs manquantes. - Un honnête lequel utiliser quand pour quiconque navigue entre les deux langages.
Si vous écrivez déjà du R et devez désormais lire du Python (ou l’inverse), vous n’avez pas besoin de réapprendre à programmer — vous avez besoin d’une carte reliant la syntaxe que vous connaissez à son jumeau dans l’autre langage. Ce guide est cette carte. Le code R ci-dessous s’exécute et affiche le résultat que vous voyez ; le Python est du code vérifié que vous pouvez copier-coller et exécuter, avec chaque résultat décrit en prose.
Les deux différences qui piègent tout le monde
L’essentiel de R et Python se lit de la même façon une fois le vocabulaire connu. Deux différences, cependant, causent l’écrasante majorité des bugs quand on passe de l’un à l’autre — intégrez-les d’abord :
- Base d’indexation. R compte les positions à partir de 1 ; Python à partir de 0. Ainsi, le premier élément est
x[1]en R maisx[0]en Python. C’est la source la plus fréquente d’erreurs à un indice près (« off-by-one ») quand on passe d’un langage à l’autre — elle a sa propre section ci-dessous. - R est vectorisé par défaut ; Python ne l’est pas. En R, l’unité fondamentale est le vecteur —
1:5 + 10ajoute 10 à chaque élément sans boucle, car il n’y a pas de scalaires isolés (un nombre seul n’est qu’un vecteur de longueur 1). En Python, un simple nombre est un scalaire et unelistordinaire ne fait pas de calcul élément par élément ([1, 2, 3] + [10]concatène au lieu d’additionner) ; vous vous tournez vers un tableau NumPy pour obtenir l’arithmétique vectorisée façon R.
Tout le reste est un remplacement direct. Voici tout l’aide-mémoire en un seul tableau :
| Construction | R | Python |
|---|---|---|
| Affecter une valeur | x <- 10 (ou x = 10) |
x = 10 |
| Commentaire | # comment |
# comment |
| Afficher | print(x) |
print(x) |
| Une collection | vecteur c(1, 2, 3) |
liste [1, 2, 3] / tableau np.array([1,2,3]) |
| Premier élément | x[1] — à base 1 |
x[0] — à base 0 |
| Dernier élément | x[length(x)] / tail(x, 1) |
x[-1] |
| Découper les deux premiers | x[1:2] |
x[0:2] (borne de fin exclue) |
| Puissance | 2^10 |
2 ** 10 |
| Division entière / modulo | 7 %/% 2 / 7 %% 2 |
7 // 2 / 7 % 2 |
| Égal / différent | == / != |
== / != |
| Et / ou / non logiques | && || ! (scalaire) ; & | (vecteur) |
and or not |
if / else |
if (c) {...} else {...} |
if c: / else: (indentation, pas d’accolades) |
| Sinon-si | else if (c) {...} |
elif c: |
| Boucle for | for (i in 1:3) {...} |
for i in range(1, 4): |
| Boucle while | while (c) {...} |
while c: |
| Définir une fonction | f <- function(x) { ... } |
def f(x): ... |
| Renvoyer | return(x) (ou dernière valeur) |
return x |
| Charger un package | library(dplyr) |
import numpy as np |
| Concaténer des chaînes | paste0("a", "b") |
"a" + "b" |
| Gestion des erreurs | tryCatch(expr, error = function(e) ...) |
try: ... except ...: |
| Longueur d’une chaîne | nchar(s) |
len(s) |
| Valeur manquante | NA |
None / float("nan") |
| Délimiteur de bloc | accolades { } |
indentation (pas d’accolades) |
| Fin d’instruction | saut de ligne (; facultatif) |
saut de ligne (; facultatif) |
Gardez ce tableau ouvert les premières fois ; vous cesserez vite d’en avoir besoin. Le reste du guide parcourt chaque ligne avec un exemple exécutable.
Commentaires et affectation
Les plus petites choses d’abord. Les commentaires commencent par # dans les deux langages — rien à réapprendre. L’affectation, elle, a une particularité en R : son opérateur idiomatique est la flèche gauche <-, même si = fonctionne aussi ; Python n’utilise que =. Les deux print() ensuite de la même façon.
# Variable assignment and arithmetic in R
a <- 10
b <- 5
total <- a + b
product <- a * b
print(paste("Sum:", total))[1] "Sum: 15"
print(paste("Product:", product))[1] "Product: 50"
# Variable assignment and arithmetic in Python
a = 10
b = 5
total = a + b
product = a * b
print("Sum:", total)
print("Product:", product)Sortie : Sum: 15 puis Product: 50 — des nombres identiques. Deux remarques de style : la convention de la communauté R est <- pour l’affectation (la plupart des bases de code R et le guide de style tidyverse l’emploient), tandis que Python n’a que =. Et le print(paste(...)) de R colle d’abord les morceaux en une seule chaîne ; le print() de Python prend plusieurs arguments et insère une espace entre eux, si bien que vous écrivez directement print("Sum:", total).
Types de données fondamentaux
Les deux langages ont des entiers, des décimaux (virgule flottante), du texte (chaînes de caractères) et des booléens. Les valeurs se ressemblent ; les noms de types diffèrent légèrement. Vérifiez le type d’une valeur avec class() en R et type() en Python.
x <- 42L # integer (the L makes it an integer, not a double)
y <- 3.14 # double (R's default numeric type)
name <- "Ada" # character
flag <- TRUE # logical
c(class(x), class(y), class(name), class(flag))[1] "integer" "numeric" "character" "logical"
x = 42 # int
y = 3.14 # float
name = "Ada" # str
flag = True # bool
print(type(x), type(y), type(name), type(flag))Sortie : R indique "integer", "numeric" (son nom pour un double), "character", "logical" ; Python indique <class 'int'>, <class 'float'>, <class 'str'>, <class 'bool'>. Les mêmes quatre idées, des étiquettes différentes. Deux orthographes à retenir : R écrit le texte "character" et les booléens en MAJUSCULES TRUE/FALSE, tandis que Python utilise str et les capitalisés True/False.
Vecteurs et listes
Ici les langages divergent d’une manière qui mérite d’être comprise, pas seulement mémorisée. La collection de tous les jours en R est le vecteur (c(...)), dont les éléments doivent tous être du même type et qui fait l’arithmétique élément par élément. La collection de tous les jours en Python est la list ([...]), qui peut mêler les types mais ne fait pas de calcul élément par élément — pour cela, vous utilisez un tableau NumPy, qui se comporte comme un vecteur R.
fruits <- c("apple", "banana", "cherry") # a character vector
nums <- c(1, 2, 3, 4, 5) # a numeric vector
print(fruits)[1] "apple" "banana" "cherry"
print(nums + 10) # vectorized: adds 10 to each element[1] 11 12 13 14 15
import numpy as np
fruits = ["apple", "banana", "cherry"] # a list
nums = np.array([1, 2, 3, 4, 5]) # a NumPy array (R-style vector)
print(fruits)
print(nums + 10) # vectorized: adds 10 to each element
# a plain list does NOT do element-wise math:
print([1, 2, 3] + [10]) # -> [1, 2, 3, 10] (concatenation!)Sortie : les deux affichent les trois fruits, puis 11 12 13 14 15 — le tableau NumPy ajoute 10 à chaque élément exactement comme le vecteur R. La dernière ligne est le piège que tout utilisateur de R rencontre : [1, 2, 3] + [10] renvoie [1, 2, 3, 10] — le + de Python sur des listes ordinaires les joint au lieu de les additionner. Tournez-vous vers np.array chaque fois que vous voulez l’arithmétique vectorisée de R.
Indexation : à base 1 (R) vs à base 0 (Python)
R indexe à partir de 1. Python indexe à partir de 0. Le premier élément est x[1] en R et x[0] en Python. Les tranches diffèrent aussi : l’indice de fin de Python est exclu, donc x[0:2] renvoie les éléments aux positions 0 et 1 (les deux premiers), pas trois. Trompez-vous là-dessus et chaque position de votre code est décalée d’un cran.
La même collection de quatre éléments, accédée des deux façons :
vec <- c("a", "b", "c", "d")
vec[1] # first element -> "a"[1] "a"
vec[2] # second element -> "b"[1] "b"
vec[length(vec)] # last element -> "d"[1] "d"
vec[1:2] # first two -> "a" "b"[1] "a" "b"
vec = ["a", "b", "c", "d"]
print(vec[0]) # first element -> "a"
print(vec[1]) # second element -> "b"
print(vec[-1]) # last element -> "d" (negative counts from the end)
print(vec[0:2]) # first two -> ['a', 'b'] (stop is exclusive)Sortie : R renvoie "a", "b", "d", puis "a" "b" ; Python renvoie a, b, d, puis ['a', 'b'] — les mêmes quatre éléments atteints par des numéros de position différents. Deux commodités de Python sans équivalent R direct : les indices négatifs comptent depuis la fin (vec[-1] est le dernier élément, là où R écrirait vec[length(vec)] ou tail(vec, 1)), et la tranche [0:2] s’arrête avant l’indice 2. Répétez-vous « R commence à un, Python commence à zéro » jusqu’à ce que ce soit automatique — c’est la différence qui cause le plus de bugs.
Arithmétique et opérateurs
Les quatre opérateurs de base (+ - * /) sont identiques. Trois diffèrent par leur écriture : la puissance, la division entière (partie entière) et le modulo (reste).
c(7 + 2, 7 - 2, 7 * 2, 7 / 2) # add, subtract, multiply, divide[1] 9.0 5.0 14.0 3.5
7^2 # power -> 49[1] 49
7 %% 2 # modulo -> 1[1] 1
7 %/% 2 # floor divide -> 3[1] 3
print(7 + 2, 7 - 2, 7 * 2, 7 / 2) # add, subtract, multiply, divide
print(7 ** 2) # power -> 49
print(7 % 2) # modulo -> 1
print(7 // 2) # floor divide -> 3Sortie : les deux calculent 9, 5, 14, 3.5 pour les quatre opérations de base — bien que R les affiche 9.0 5.0 14.0 3.5 parce que le 7 / 2 convertit tout le vecteur en double, tandis que Python garde 9 5 14 en entiers et seul 3.5 en flottant — puis 49, 1, 3. Les seules choses à réapprendre : la puissance est ^ en R mais ** en Python, la division entière est %/% vs //, et le modulo est %% vs %. (Attention : ^ en Python est le OU exclusif bit à bit, pas la puissance — une réponse fausse et silencieuse si vous transposez l’habitude de R.)
Opérateurs de comparaison et logiques
Les comparaisons (>, <, >=, <=, ==, !=) sont identiques dans les deux langages. C’est du côté des opérateurs logiques que R ajoute une subtilité : il distingue les formes scalaires &&/|| (comparer une seule valeur, utilisées dans les conditions if) des formes vectorisées &/| (comparer élément par élément sur tout un vecteur). Python n’a que les mots and, or, not.
x <- 7
c(x > 5, x == 7, x != 3) # TRUE TRUE TRUE[1] TRUE TRUE TRUE
(x > 5) && (x < 10) # scalar AND -> TRUE[1] TRUE
(x > 5) || (x > 100) # scalar OR -> TRUE[1] TRUE
!(x > 5) # NOT -> FALSE[1] FALSE
x = 7
print(x > 5, x == 7, x != 3) # True True True
print(x > 5 and x < 10) # AND -> True
print(x > 5 or x > 100) # OR -> True
print(not x > 5) # NOT -> FalseSortie : les deux signalent trois comparaisons TRUE/True, puis TRUE, TRUE, FALSE. La correspondance est &&→and, ||→or, !→not. La seule habitude à prendre : en R, utilisez les doublés &&/|| à l’intérieur d’un if() (valeur unique) et les simples &/| pour filtrer un vecteur entier ; les opérateurs-mots de Python couvrent le cas de la valeur unique et les &/| de NumPy gèrent le cas élément par élément.
if / else
Même logique, ponctuation différente. R entoure la condition de parenthèses et le corps d’accolades { }. Python place un deux-points après la condition et marque le corps par l’indentation — aucune accolade nulle part. Le else if de R devient le elif de Python.
score <- 72
if (score >= 90) {
grade <- "A"
} else if (score >= 60) {
grade <- "B"
} else {
grade <- "C"
}
print(grade)[1] "B"
score = 72
if score >= 90:
grade = "A"
elif score >= 60:
grade = "B"
else:
grade = "C"
print(grade)Sortie : les deux affichent "B" (72 franchit le seuil de 60 mais pas celui de 90). C’est l’endroit le plus clair pour voir l’habitude qui définit Python : l’indentation est de la syntaxe. Là où R utilise { } pour délimiter le bloc, Python utilise le niveau d’indentation lui-même — quatre espaces est la convention, et une indentation incohérente est une vraie erreur, pas un détail de style.
Boucles : for et while
Les deux langages ont for et while. Le for de R itère sur une séquence écrite avec 1:n ; Python itère sur range(), et ici la règle à base 0, fin exclue réapparaît : range(1, 4) produit 1, 2, 3 — la valeur de fin 4 n’est pas incluse.
for (i in 1:3) {
print(paste("Iteration", i))
}[1] "Iteration 1"
[1] "Iteration 2"
[1] "Iteration 3"
n <- 3
while (n > 0) {
print(paste("Countdown", n))
n <- n - 1
}[1] "Countdown 3"
[1] "Countdown 2"
[1] "Countdown 1"
for i in range(1, 4): # range stops BEFORE 4 -> 1, 2, 3
print("Iteration", i)
n = 3
while n > 0:
print("Countdown", n)
n -= 1 # shorthand for n = n - 1Sortie : les deux affichent Iteration 1/2/3 puis Countdown 3/2/1. Le piège est range() : pour boucler trois fois, vous écrivez range(1, 4) ou, plus courant, range(3) (qui produit 0, 1, 2). Deux commodités de Python : range(3) partant de 0 est le décompte idiomatique, et n -= 1 est un raccourci pour n = n - 1. Un réflexe à cultiver tôt, cependant — dans les deux langages, une boucle explicite est souvent la voie lente ; préférez les opérations vectorisées de R ou le calcul sur tableaux de NumPy quand vous le pouvez.
Fonctions
R affecte une function(...) anonyme à un nom ; Python utilise le mot-clé def. R peut renvoyer une valeur avec return() mais renvoie aussi automatiquement sa dernière expression évaluée, si bien que le return() est souvent omis ; Python exige un return explicite pour renvoyer une valeur.
square <- function(x) {
x^2 # the last expression is returned automatically
}
square(4) # -> 16[1] 16
def square(x):
return x ** 2 # Python needs an explicit return
print(square(4)) # -> 16Sortie : les deux renvoient 16. La différence structurelle : en R, une fonction est une valeur que vous affectez (square <- function(x) ...), ce qui explique pourquoi vous pouvez faire circuler les fonctions si librement ; en Python, def est une instruction qui lie le nom pour vous. Et souvenez-vous du renvoi implicite de R — la valeur de la dernière ligne revient sans return(), tandis qu’omettre return dans une fonction Python lui fait renvoyer None.
Packages : library() vs import
Les deux langages livrent un immense écosystème de packages additionnels. R en charge un avec library(name), après quoi chacune de ses fonctions est disponible telle quelle (filter(), mean()). Python importe un module et vous appelez généralement à travers son nom (np.sqrt), ce qui garde explicite l’origine de chaque fonction — le courant import numpy as np lui donne un alias court.
library(stats) # (base R; loaded already — shown for the pattern)
sqrt(16) # -> 4[1] 4
mean(c(1, 2, 3, 4)) # -> 2.5[1] 2.5
import numpy as np # whole module, aliased to np
from statistics import mean # pull one name into scope
print(np.sqrt(16)) # -> 4.0 (called through the alias)
print(mean([1, 2, 3, 4])) # -> 2.5 (imported name, called bare)Sortie : les deux donnent 4 et 2.5. Le changement mental est l’espace de noms : après library(), les fonctions R s’appellent telles quelles, donc deux packages peuvent entrer en conflit sur un nom (le dernier chargé l’emporte). Le import numpy as np de Python garde les fonctions derrière leur module (np.sqrt), si bien qu’il est toujours clair d’où vient une fonction — ou vous utilisez from module import name pour amener un seul nom dans la portée, plus proche du style de R. L’installation est l’autre moitié : install.packages("pkg") en R, pip install pkg dans le terminal en Python.
Chaînes de caractères
Les bases du texte se correspondent proprement, avec une différence notable : Python colle les chaînes avec +, tandis que R n’a pas de + sur les chaînes et utilise à la place paste0() (sans séparateur) ou paste() (séparées par une espace).
first <- "data"
second <- "novia"
paste0(first, second) # concatenate -> "datanovia"[1] "datanovia"
nchar("datanovia") # length -> 9[1] 9
toupper("data") # upper-case -> "DATA"[1] "DATA"
sprintf("%s-%s", first, second) # format -> "data-novia"[1] "data-novia"
first = "data"
second = "novia"
print(first + second) # concatenate -> datanovia
print(len("datanovia")) # length -> 9
print("data".upper()) # upper-case -> DATA
print(f"{first}-{second}") # f-string -> data-noviaSortie : les deux produisent datanovia, 9, DATA et data-novia. Les quatre opérations se correspondent ainsi : paste0→+, nchar→len, toupper→.upper(), et sprintf/paste→ la f-string f"{first}-{second}" (le gabarit en ligne de Python, la façon la plus nette d’interpoler des variables dans du texte). Notez que .upper() est une méthode appelée sur la chaîne — le style objet de Python — là où le toupper() de R est une simple fonction à laquelle vous passez la chaîne.
Valeurs manquantes : NA vs None et NaN
Tout langage de données a besoin d’une façon de dire « aucune valeur ici », et c’est une source fréquente de confusion. R a un unique NA de première classe qui se propage à travers les calculs (et existe en variantes typées comme NA_real_). Python scinde l’idée en deux : None est l’objet général « rien », tandis que float("nan") (généralement np.nan) est le « pas un nombre » numérique utilisé au sein des tableaux et des data frames.
nums <- c(1, NA, 3)
is.na(nums) # which are missing -> FALSE TRUE FALSE[1] FALSE TRUE FALSE
sum(nums) # propagates -> NA[1] NA
sum(nums, na.rm = TRUE) # skip missing -> 4[1] 4
import numpy as np
nums = [1.0, np.nan, 3.0]
arr = np.array(nums)
print(np.isnan(arr)) # which are missing -> [False True False]
print(arr.sum()) # propagates -> nan
print(np.nansum(arr)) # skip missing -> 4.0Sortie : les deux signalent la valeur du milieu comme manquante (FALSE TRUE FALSE / [False True False]), les deux propagent — une simple somme renvoie NA en R et nan en Python — et les deux offrent une voie pour ignorer les manquants : l’argument na.rm = TRUE de R donne 4, le np.nansum() de Python donne 4.0. Le concept à retenir : l’unique NA de R fait le travail des deux idées de Python — utilisez None pour un objet manquant (un emplacement vide, une fonction qui n’a rien renvoyé) et NaN pour un nombre manquant au sein des tableaux et des frames pandas. Le test se fait avec is.na() en R et np.isnan() (nombres) ou x is None (objets) en Python.
Lequel utiliser quand
Oubliez le tribalisme — choisissez selon le contexte :
- Optez pour R quand votre travail relève des statistiques, de la visualisation de données, du reporting ou de la bioinformatique — le langage et ses packages (le tidyverse, ggplot2, l’écosystème statistique de CRAN) ont été bâtis par et pour les analystes de données, et son style vectorisé, orienté objet entier, rend l’analyse exploratoire concise et expressive.
- Optez pour Python quand vous avez besoin de programmation généraliste autour du travail sur les données — applications web, automatisation, apprentissage profond (PyTorch, scikit-learn), pipelines de production — ou quand vous transmettez des données à l’écosystème logiciel plus large. Sa syntaxe lisible, guidée par l’indentation, et son immense base de bibliothèques en font le langage de liaison par défaut.
- Vous n’avez pas à choisir. Les concepts — variables, types, collections, indexation, structures de contrôle, fonctions, packages — sont la même poignée d’idées dans les deux. Apprenez-les une fois et le second langage n’est surtout qu’un changement de vocabulaire, plus les deux pièges ci-dessus (l’indexation à base 0 et le calcul liste-vs-tableau). Beaucoup de data scientists lisent et écrivent les deux au quotidien.
La bonne nouvelle pour quiconque navigue entre les deux : une fois les deux différences du début de ce guide devenues automatiques, tout le reste n’est que le tableau de correspondance.
Foire aux questions
Cela reflète l’héritage de chaque langage. R a hérité l’indexation à base 1 de S et de la tradition mathématique/statistique, où le « premier » élément est naturellement l’élément numéro 1. Python suit la convention informatique (partagée avec C, Java et la plupart des langages généralistes) où un indice est un décalage par rapport au début, si bien que le premier élément se trouve au décalage 0. Aucune n’est « correcte » — mais les confondre est le bug numéro un du changement de langage, donc la règle à mémoriser est simplement : premier élément en R = x[1], premier élément en Python = x[0].
import de Python ?
library(package). Après library(dplyr), chaque fonction du package est disponible par son nom nu (filter()), comme le from module import * de Python. L’analogue le plus proche de import numpy as np — garder les fonctions derrière un espace de noms — est la forme package::function() de R (par ex. dplyr::filter()), qui appelle une fonction sans attacher tout le package. L’installation se fait avec install.packages("pkg") en R contre pip install pkg en Python.
<- ou = pour l’affectation en R ?
Les deux fonctionnent, mais la convention de la communauté R est la flèche gauche <- pour affecter des variables, réservant = aux arguments nommés de fonction (mean(x, na.rm = TRUE)). Suivre cette convention fait que votre R se lit comme du R idiomatique et évite quelques cas particuliers où = se comporte différemment. Python n’a pas ce choix — l’affectation est toujours =.
NA, None et NaN ?
NA est le marqueur unique et de première classe de R pour une valeur manquante ; il se propage à travers les calculs (sum(c(1, NA)) vaut NA) sauf si vous passez na.rm = TRUE. Python scinde l’idée : None est la valeur générale « aucun objet ici » (un emplacement vide, une fonction qui n’a rien renvoyé), tandis que NaN (« pas un nombre », float("nan") ou np.nan) est la valeur manquante numérique utilisée au sein des tableaux NumPy et des data frames pandas. Testez avec is.na() en R, et np.isnan() (pour les nombres) ou x is None (pour les objets) en Python.
Cela dépend de votre objectif. Si votre travail relève des statistiques, de la visualisation ou du reporting, la conception centrée sur les données de R et sa syntaxe vectorisée semblent souvent plus naturelles plus tôt. Si vous visez la programmation généraliste, l’automatisation ou l’apprentissage automatique, la syntaxe lisible de Python et son vaste écosystème en font le premier langage le plus transférable. La partie rassurante : la syntaxe de base que vous venez de voir — variables, types, collections, structures de contrôle, fonctions — est presque la même dans les deux, si bien qu’apprendre le second langage n’est surtout qu’un changement de syntaxe, pas un nouveau départ.
Pour aller plus loin
- Fondamentaux de R — les bases de R exécutables : vecteurs et types, listes, indexation et sous-ensembles, structures de contrôle, écrire des fonctions et installer des packages.
- Fondamentaux de Python — le côté Python : bases de Python, types et structures de données et tableaux NumPy.
- dplyr vs pandas et ggplot2 vs matplotlib — les guides frères R ↔︎ Python pour la manipulation de données et le traçage, une fois la syntaxe maîtrisée.
Demandez à Prova « réécris ce script R en Python, en gardant la même logique et en corrigeant l’indexation à base 1 » — collez votre propre code et elle répond avec une version que vous pouvez exécuter. The runtime is the judge. Demander à Prova →
Citation
@online{kassambara2026,
author = {Kassambara, Alboukadel},
title = {Syntaxe R vs Python : guide côte à côte},
date = {2026-07-14},
url = {https://www.datanovia.com/blog/r-vs-python-syntax},
langid = {fr}
}