Python
Initialiser jupyter via WSL
mkdir python_juin_2026
cd python_juin_2026
wget -qO- https://astral.sh/uv/install.sh | sh # installation de UV
uv init
uv add jupyter
uv run jupyter lab
Numpy
# np.random.seed + np.random.normal : données aléatoires reproductibles
np.random.seed(42) # fixation du générateur de nombres aléatoires (pour reproductibilité)
bruit = np.random.normal(loc=0, scale=0.5, size=(3, 4)) # où loc est la moyenne et scale l'écart type
bruit
Masque booléen
Un masque booléen est un tableau de True/False obtenu en appliquant une condition sur un tableau. Il permet de sélectionner ou de modifier des éléments selon un critère, sans boucle.
masque_froid = carte_temp < 14.0
masque_froid
np.sum(masque_froid) # True est traité comme 1
# Extraire uniquement les valeurs froides
carte_temp[masque_froid]
# Remplacer des valeurs : les cellules > 17degC sont marquées comme anomalie (np.nan)
carte_modif = carte_temp.copy() # toujours travailler sur une copie
carte_modif[carte_temp > 17.0] = np.nan
carte_modif
Gestion des données manquantes
# Détecter les NaN
np.isnan(array)
# Calculs en ignorant les NaN
print("Moyenne (avec NaN ignorés) :", np.nanmean(mesures))
print("Max (avec NaN ignorés) :", np.nanmax(mesures))
print("Somme (avec NaN ignorés) :", np.nansum(mesures))
Reshape
# Convertir en matrice 3x4
mat = v.reshape(3, 4)
# flatten() : retourner à un vecteur (renvoie une copie)
mat.flatten()
# ravel() : idem mais renvoie une vue (plus efficace en mémoire)
mat.ravel()
# Ajouter une dimension (utile pour le broadcasting ou RasterIO)
# Une image raster à une bande a la forme (1, H, W)
mat_3d = mat[np.newaxis, :, :] # shape (1, 3, 4)
print("Avant :", mat.shape)
print("Après :", mat_3d.shape)
Visualisation d'un tableau 2D
# La colormap 'terrain' est appropriée pour les élévations.
# D'autres options utiles : 'gray', 'viridis', 'RdYlGn'
fig, axes = plt.subplots(1, 3, figsize=(14, 4))
for ax, cmap in zip(axes, ['terrain', 'gray', 'viridis']):
im = ax.imshow(altitude_synth, cmap=cmap)
plt.colorbar(im, ax=ax, label='Altitude (m)')
ax.set_title(f'cmap = {cmap!r}')
plt.tight_layout()
plt.show()
Récapitulatif des fonctions utiles
| Fonction | Rôle |
|---|---|
| np.array([...]) | Créer un tableau à partir d’une liste |
| np.zeros(shape) | Tableau de zéros |
| np.ones(shape) | Tableau de uns |
| np.arange(start, stop, step) | Suite de valeurs espacées d’un pas |
| np.linspace(start, stop, n) | n valeurs régulièrement espacées |
| arr.shape | Dimensions du tableau |
| arr.ndim | Nombre de dimensions |
| arr.size | Nombre total d’éléments |
| arr.dtype | Type des données |
| arr.reshape(shape) | Changer la forme (sans copier) |
| arr.flatten() | Remettre à plat (copie) |
| arr.copy() | Copie indépendante |
| np.sum / min / max / mean / std | Statistiques globales |
| np.nanmean / nanmax / nansum | Statistiques en ignorant les NaN |
| np.isnan(arr) | Masque des NaN |
| arr[masque] | Sélection par masque booléen |
| plt.imshow(arr, cmap=...) | Visualiser un tableau 2D comme image |
Pandas
DataFrame
df = pd.DataFrame({
'nom' : ['Tarbes', 'Lourdes', 'Bagnères', 'Arreau', 'Saint-Lary'],
'altitude' : [320, 420, 550, 720, 830],
'temp_moy' : [15.5, 14.8, 13.9, 11.2, 10.4],
'pluvio' : [850, 1050, 1200, 1400, 1600],
})
# Aperçu des premières lignes
df.head()
# Aperçu des dernières lignes
df.tail(3)
# Résumé : types, mémoire, valeurs non-nulles
df.info()
# Statistiques descriptives des colonnes numériques
df.describe()
# Noms des colonnes
df.columns
# Index des lignes (entiers par défaut)
df.index
# Nombre total d'éléments
df.size
# Dimensions : (nombre de lignes, nombre de colonnes)
df.shape
# Type de chaque colonne
df.dtypes
# Accéder à une colonne entière -> renvoie une Series
df.loc[:, 'altitude']
# Raccourci équivalent (notation crochets)
df['altitude']
# Accéder à plusieurs colonnes -> renvoie un DataFrame
df.loc[:, ['nom', 'altitude', 'temp_moy']]
# Raccourci équivalent
df[['nom', 'altitude', 'temp_moy']]
# Accéder à une ligne par son index entier (ici index 0 = Tarbes)
df.loc[0]
# Accéder à une cellule précise : ligne 1, colonne 'temp_moy'
df.loc[1, 'temp_moy']
Pont Numpy <=> Pandas
# .values renvoie un ndarray NumPy (c'est le pont NumPy <-> Pandas)
altitudes = df['altitude'].values
print(type(altitudes))
print(altitudes)
# On peut alors utiliser toutes les fonctions NumPy
print("Altitude moyenne :", np.mean(altitudes))
print("Altitude max :", np.max(altitudes))
print("Écart-type :", np.std(altitudes))
Sélection conditionnelle
Pandas permet de filtrer les lignes selon une condition, exactement comme les masques booléens NumPy.
# La condition produit une Series de booléens
df['altitude'] > 600
# Utiliser cette Series comme masque pour filtrer le DataFrame
df[df['altitude'] > 600]
# Combiner plusieurs conditions : & (ET), | (OU), ~ (NON)
# Attention : chaque condition doit être entre parenthèses
df[(df['altitude'] > 400) & (df['temp_moy'] < 14.0)]
df_filtered=df[(df['altitude']>400) & (df['altitude']<700)]
Nouvelle colonne
df['temp_fahrenheit'] = df['temp_moy'] * 9/5 + 32
# Catégorie d'altitude en 3 niveaux
df['categorie'] = np.where(
df['altitude'] < 400, 'Plaine',
np.where(df['altitude'] < 700, 'Colline', 'Montagne')
)
df[['nom', 'altitude', 'categorie']]
Appliquer une fonction à tous les éléments
# Appliquer une fonction personnalisée
def classer_temp(t):
if t < 12:
return 'froid'
elif t < 15:
return 'tempéré'
else:
return 'chaud'
df['climat'] = df['temp_moy'].apply(classer_temp)
df[['nom', 'temp_moy', 'climat']]
Supprimer une colonne
# Supprimer les colonnes de travail (inplace=True modifie directement le DataFrame)
df.drop(columns=['temp_fahrenheit',
'nom_maj', 'climat'], inplace=True)
df
Gestion des valeurs manquantes
# Créer un DataFrame avec des NaN
df_incomplet = pd.DataFrame({
'station' : ['A', 'B', 'C', 'D', 'E'],
'altitude' : [320, np.nan, 550, 720, np.nan],
'temp_moy' : [15.5, 14.8, np.nan, 11.2, 10.4],
})
df_incomplet
# Détecter les NaN : True là où la valeur est manquante
df_incomplet.isnull()
# Compter les NaN par colonne
df_incomplet.isnull().sum()
# Supprimer les lignes contenant au moins un NaN
df_incomplet.dropna()
# Remplacer les NaN par une valeur fixe
df_incomplet.fillna(0)
Agréger avec groupby
# Nombre d'adresses par commune
adresses_par_commune = df_ban.groupby('commune_nom').size().reset_index(name='nb_adresses')
adresses_par_commune.sort_values('nb_adresses', ascending=False).head(10)
# Nombre de noms de voies distincts par commune
df_ban.groupby('commune_nom')['voie_nom'].nunique().sort_values(ascending=False).head(10)
# Plusieurs agrégations en une fois avec .agg()
df_ban.groupby('commune_nom').agg(
nb_adresses=('uid_adresse', 'count'),
nb_voies=('voie_nom', 'nunique'),
lon_moy=('long', 'mean'),
lat_moy=('lat', 'mean'),
).sort_values('nb_adresses', ascending=False).head(10)
Fonctions clés
| Fonction / Méthode | Rôle |
|---|---|
pd.DataFrame({...}) |
Créer un DataFrame depuis un dictionnaire |
pd.read_csv(path, sep=, dtype=) |
Lire un fichier CSV |
df.to_csv(path, index=False) |
Écrire un fichier CSV |
df.head(n) / df.tail(n) |
Aperçu des premières / dernières lignes |
df.info() |
Types, mémoire, valeurs non-nulles |
df.describe() |
Statistiques descriptives |
df.shape / df.size |
Dimensions / nombre total d'éléments |
df.dtypes |
Type de chaque colonne |
df.columns / df.index |
Étiquettes de colonnes / lignes |
df.loc[lignes, colonnes] |
Sélection par étiquette |
df.iloc[lignes, colonnes] |
Sélection par position |
df['col'].values |
Récupérer le ndarray sous-jacent |
df[condition] |
Filtrage par masque booléen |
df['col'].value_counts() |
Fréquences de chaque valeur |
df['col'].nunique() |
Nombre de valeurs distinctes |
df['col'].unique() |
Liste des valeurs distinctes |
df.sort_values('col') |
Tri par colonne |
df.groupby('col').agg(...) |
Agrégation par groupe |
df.isnull() / .sum() |
Détecter / compter les NaN |
df.dropna() |
Supprimer les lignes avec NaN |
df.fillna(valeur) |
Remplacer les NaN |
df.drop(columns=[...]) |
Supprimer des colonnes |
df.rename(columns={...}) |
Renommer des colonnes |
pd.melt(df, id_vars=, value_vars=) |
Transformer wide -> long |
np.where(cond, vrai, faux) |
Créer une colonne catégorielle |
df['col'].apply(fonction) |
Appliquer une fonction élément par élément |
Exercice opérations spatiales
# À vous !
tarbes_buffer = tarbes_geom.buffer(10000)
mask = gdf_communes_l93.centroid.within(tarbes_buffer)
communes_buffer = gdf_communes_l93[mask].copy()
communes_buffer['distance_tarbes'] = communes_buffer.distance(tarbes_geom)
communes_buffer[['nom','distance_tarbes']].sort_values('distance_tarbes').head(25)