Introduction

Le melange de chaines de caracteres et d’objets du langage peut se faire par une simple concatenation mais ca n’est pas toujours tres lisible. La fonction format est un progres mais c’est encore un peu lourd :

import datetime as dttm
from sklearn import datasets
import pprint
pp = pprint.PrettyPrinter(indent = 1)
import pandas as pd
pd.set_option('display.max_columns', None)

x = 2
y = 6

"J'ai achete " + str(x) + " croissants et " + str(y) + " chouquettes"
"J'ai achete 2 croissants et 6 chouquettes"
"j'ai achete {x} croissants et {y} chouquettes".format(x = x, y = y)
"j'ai achete 2 croissants et 6 chouquettes"

Les f-strings en Python et le package glue en R permettent d’obtenir un code plus court et intuitif, avec pratiquement la meme syntaxe.

Avec Python

Un f-string

f"J'ai achete {x} croissants et {y} chouquettes"
"J'ai achete 2 croissants et 6 chouquettes"

Avec un peu de formatage

La forme generale est f"{valeur:formatage}". On peut par exemple utiliser”_” ou “,” comme separateur de milliers et lui substituer un espace juste apres pour un format plus europeen :

nb_lignes = 1234567
nb_colonnes = 123

pp.pprint({"Nombre de lignes du dataframe" :  f"{nb_lignes:_}".replace("_", " "),
"Nombre de colonnes du dataframe" :  f"{nb_colonnes:_}".replace("_", " ")})
{'Nombre de colonnes du dataframe': '123',
 'Nombre de lignes du dataframe': '1 234 567'}

On justifie a droite avec “>”, on centre avec “^”, on peut ajouter une largeur minimale souhaitee, cf https://docs.python.org/fr/3/library/string.html#formatspec pour toutes les possibilites. On peut aussi ecrire les f-strings sur plusieurs lignes comme ci-dessous pour rendre le code plus lisible.

nombre = -12345.6789
date_jour = dttm.datetime.now()

message = (
  f"La date du jour : Le {date_jour:%Y-%m-%d}"
  f" a {date_jour:%H:%M}.\n"
  f"""Un nombre : {nombre : >10.1f} justifie a droite,
un nombre : {nombre : <10.2f} justifie a gauche
et un dernier {nombre : ^20_.3f} au centre"""
)

print(message)
La date du jour : Le 2024-01-19 a 20:54.
Un nombre :   -12345.7 justifie a droite,
un nombre : -12345.68  justifie a gauche
et un dernier     -12_345.679      au centre

Dans un DataFrame

iris = datasets.load_iris()
X = pd.DataFrame(iris.data)
X.columns = ['Sepal_length', 'Sepal_width', 'Petal_length', 'Petal_width']
X["Species"] = pd.Series(iris.target).map({0:'setosa', 1:'versicolor', 2:'vitginica'})


X["texte"] = X.apply(lambda dtf: 
  f"Cette {dtf.Species} a des petales de longueur {dtf.Petal_length}", axis = 1)
X.head(5)
   Sepal_length  Sepal_width  Petal_length  Petal_width Species  \
0           5.1          3.5           1.4          0.2  setosa   
1           4.9          3.0           1.4          0.2  setosa   
2           4.7          3.2           1.3          0.2  setosa   
3           4.6          3.1           1.5          0.2  setosa   
4           5.0          3.6           1.4          0.2  setosa   

                                        texte  
0  Cette setosa a des petales de longueur 1.4  
1  Cette setosa a des petales de longueur 1.4  
2  Cette setosa a des petales de longueur 1.3  
3  Cette setosa a des petales de longueur 1.5  
4  Cette setosa a des petales de longueur 1.4  

Avec glue

Comparaison glue / concatenation

library("glue")
library("dplyr")
glue('Infos avec glue : \nThis dataset has {nrow(mtcars)} rows and {ncol(mtcars)} columns. There {
     ifelse(sum(is.na(mtcars))>0,"is","are")} {sum(is.na(mtcars))} Missing Value')

cat(paste('\nInfos avec paste : \nThis dataset has', nrow(mtcars), 'rows and', ncol(mtcars), 
          'columns. There', ifelse(sum(is.na(mtcars))>0,"is","are"), sum(is.na(mtcars)), 
          'Missing Value'))
Infos avec glue : 
This dataset has 32 rows and 11 columns. There are 0 Missing Value

Infos avec paste : 
This dataset has 32 rows and 11 columns. There are 0 Missing Value

Avec des arguments nommes

On retrouve la syntaxe de la fonction Python format.

glue('My name is {name}, my age next year is {age + 1}, my anniversary is {format(anniversary, 
                                                                          "%A, %B %d, %Y")}.',
     name = "Joe",
     age = 40,
     anniversary = as.Date("2001-10-12"))
My name is Joe, my age next year is 41, my anniversary is vendredi, octobre 12, 2001.

Avec le pipe du package magrittr

iris[1:3,] %>% mutate(texte = glue("Cette {Species} a des petales de longueur {Petal.Length}"))
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
                                       texte
1 Cette setosa a des petales de longueur 1.4
2 Cette setosa a des petales de longueur 1.4
3 Cette setosa a des petales de longueur 1.3

La fonction glue_data permet de referencer le dataframe entier dans des pipes.

head(mtcars) %>% glue_data("{rownames(.)} has {hp} hp")
Mazda RX4 has 110 hp
Mazda RX4 Wag has 110 hp
Datsun 710 has 93 hp
Hornet 4 Drive has 110 hp
Hornet Sportabout has 175 hp
Valiant has 105 hp

retour au debut du document