Créer des visualisations avancées et uniques dans Power BI avec Python

(Last Updated On: )

Saviez-vous qu’il est possible de créer ses propres visuels dans Power BI en Python 🐍 ?
Mais pourquoi vouloir s’embêter avec du code Python alors que la Marketplace offre déjà tant de visuels supplémentaires  ? 🤔

Voici mon expérience : récemment, un client m’a demandé de comparer une entreprise à la moyenne du marché sur six axes d’analyse. Malheureusement, aucun visuel natif n’était satisfaisant pour ce besoin. J’ai donc pensé à un Radar plot et j’ai téléchargé celui de Microsoft depuis la marketplace… avant de réaliser à quel point il manquait de flexibilité. Pas le temps (ni le budget) de (faire) développer un Custom Visual, alors j’ai jeté un œil du côté des visuels Python.

Avec seulement quelques lignes de code, et l’aide de ChatGPT 💡, j’ai réussi à créer un Radar plot entièrement personnalisé. Non seulement la solution a répondu aux attentes, mais elle été rapide à mettre en place et prouve que les visuels Python peuvent combler dans certains cas les limites des visuels standards dans Power BI.

Dans cet article, je vous montre pas à pas comment créer de tels visuels Python dans Power BI pour réaliser des visualisations avancées sans être un expert du développement — tout en vous mettant en garde de certaines limitations (oui, il y en a). Bonne lecture ! 🚀

Quand et pourquoi utiliser des visuels Python

Python est aujourd’hui l’un des langages les plus populaires en Data Science et en Data Analysis, notamment grâce à ses librairies puissantes comme NumPy, Pandas, Matplotlib, Scikit-learn, etc. Il se prête aussi bien à l’exploration de données, à la modélisation qu’à la production de visualisations avancées et à la création de modèle d’Intelligence Artificielle 🤩. Avec une communauté très active et une courbe d’apprentissage assez douce, Python est devenu un incontournable pour quiconque veut dynamiser ses projets data.

Je vois pour moi 2 raisons principales à intégrer des visuels en Python dans mes rapports Power BI :

  • Non adéquation de visuel standard ou de la place de marché avec ce que je souhaite visualiser
  • Richesse des librairies d’analyse et de visualisation de données de Python

Il existe déjà un certain nombre de visuels standards dans Power BI, ainsi que les Custom visuals disponibles sur la place de marché. Cependant, dans certains cas on peut se retrouver sans solution ni alternative, comme pour le Radar plot dans mon histoire. C’est là que les visuels Python peuvent offrir une excellente alternative.

D’un autre côté, le  langage Python est une référence en matière de bibliothèques de visualisation comme Matplotlib et Seaborn. Elles permettent notamment :

  • De personnaliser en profondeur les couleurs, formes et légendes
  • D’accéder à des visuels avancés
  • De manipuler et d’analyser les données, parfois en réalisant des calculs statistiques complexes

De plus, quitte à utiliser Python dans un visuel, rien n’empêche d’y incorporer des calculs, aggrégations, statistiques et autres, en se servant d’autres librairies phares telles que Pandas, Numpy, Scikit Learn, etc.

Voilà pour les raisons. Voyons pour le comment maintenant.

Installer Python sur sa machine

Trève de blabla, avant de pouvoir utiliser un visuel Python dans Power BI Desktop, vous devez installer Python sur votre machine, puis indiquer le chemin d’accès à l’exécutable dans Power BI. Si vous ne l’avez pas déjà fait, voici les grandes étapes :

  1. Téléchargez et installez Python (idéalement la version 64 bits) depuis le site officiel de Python par exemple. Pour ma part, j’ai installé Winpython pour Windows
  2. Ouvrez Power BI Desktop, rendez-vous dans Fichier > Options et paramètres > Options > Création de scripts Python

  3. Sélectionnez le chemin d’accès menant à l’exécutable Python (par exemple : C:\Users\votreNom\AppData\Local\Programs\Python\Python39\python.exe)
  4. Validez

Pour en savoir plus, consultez la documentation officielle de Microsoft.

Une fois Python configuré, vous pourrez non seulement utiliser les visuels Python, mais aussi créer et exécuter des scripts Python dans Power Query (je précise que ce n’est pas le sujet ici).

Bibliothèques Python utilisables dans Power BI

Ces librairies sont supportés dans Power BI :

Il y en a plus dans Power BI Service apparemment. Celles qui nous intéressent en particulier pour créer des visuels sont :

Matplotlib

Matplotlib permet de concevoir tout un panel de graphiques (barplots, scatterplots, radar plots, etc.) tout en contrôlant finement chaque élément (couleurs, axes, titres, etc.).

Seaborn

Seaborn propose des designs plus esthétiques et intègre des fonctionnalités statistiques (heatmaps, analyses de distributions, etc.). Elle est particulièrement appréciée pour sa simplicité et son rendu visuel plus “propre”.

Création d’un visuel Python – Etape par étape

✅ Installer Python en local
✅ Préparer vos données : Chargez-les dans Power BI (via Power Query) et nettoyez-les si nécessaire (suppression des doublons, formatage des dates, etc.).
✅ Ajouter un visuel Python : Dans Power BI Desktop, sélectionnez le visuel Python. Vous verrez alors un éditeur où coller votre script Python.
✅ Glisser les champs à visualiser dans le visuel Python
✅ Rédiger un script et le copier-coller dans l’éditeur du visuel
✅ Patienter un peu, il mettra plus de temps à s’afficher que les visuels standards

Comment rédiger son script Python ?

Si comme moi vos souvenirs de Python sont déjà lointoins où que vous n’avez jamais eu l’occasion d’écrire une seule ligne de code dans ce langage, vous pouvez solliciter ChatGPT pour obtenir un exemple de script correspondant à vos besoins. Par exemple :

« Peux-tu écrire un script Python pour créer un barplot qui affiche les quantités vendues par produit? »

💡Préciser bien que vous écrivez un script pour un visuel Power BI, ainsi il intègrera la syntaxe attendue.

ChatGPT fournira un code de base, que vous pourrez ensuite personnaliser. Voici un extrait simplifié  :

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

# Exemple de préparation des données (dans Power BI, "dataset" vous est fourni tel quel)
# dataset = dataset.drop_duplicates()

# Agrégation des quantités vendues par produit
df_bar = dataset.groupby("Produit")["Quantites vendues"].sum().reset_index()

# Création de la figure
plt.figure(figsize=(10, 6))

# Barplot avec Seaborn
sns.barplot(
data=df_bar, 
x="Produit", 
y="Quantites vendues", 
color="blue"
)

# Titre et rotation des étiquettes en abscisse
plt.title("Quantités vendues par produit", fontsize=14)
plt.xticks(rotation=45, ha="right")

# Affichage du graphe
plt.tight_layout()
plt.show()

Intégration et exécution

  • Copiez-collez le script dans l’éditeur Python de Power BI, qui apparaît lorsqu’on clique sur le visuel Python
  • Validez et laissez Power BI exécuter le script localement (d’où l’importance d’avoir Python installé)

💡Important : veillez à bien ajouter les champs utilisés par le script dans le visuel Python !

Quelques exemples de visuels Python

Afin de montrer les possibilités de personnalisation offertes par ces derniers… Et comment tirer parti des packages de statistiques des données puissants de Python.

Histogramme de Marimekko

#*****************************************************************************************************
# Visuel Marimekko Chart 
#*****************************************************************************************************

# Importation des bibliothèques
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

# Agrégation des données : total des quantités vendues par Produit et Segment
df_marimekko = dataset.groupby(["Produit", "Segment"])["Quantites vendues"].sum().reset_index()

# Normalisation pour calculer la largeur et la hauteur
df_marimekko["width"] = df_marimekko.groupby("Produit")["Quantites vendues"].transform(lambda x: x / x.sum())
df_marimekko["height"] = df_marimekko["Quantites vendues"] / df_marimekko["Quantites vendues"].sum()

# Définition des couleurs fixes pour chaque segment
segment_colors = {
"BtoB": "#118DFF",
"Entreprises": "#12239E",
"Partenaires": "#E66C37",
"Services publics": "#6B007B",
"TPE": "#E044A7"
}

# Création du Marimekko Chart avec couleurs fixes et légende en haut à gauche
fig, ax = plt.subplots(figsize=(12, 8))

# Variables pour positionner les blocs
left = 0
product_positions = {} # Stocker les positions centrales des produits

for produit in df_marimekko["Produit"].unique():
subset = df_marimekko[df_marimekko["Produit"] == produit]
bottom = 0
product_width = subset["width"].sum()
product_positions[produit] = left + product_width / 2 # Position centrale du produit

for _, row in subset.iterrows():
color = segment_colors.get(row["Segment"], "#808080") # Utilisation de la couleur définie ou gris par défaut
ax.bar(left, row["height"], width=row["width"], bottom=bottom, color=color, edgecolor="black")
# Ajout des labels des quantités vendues
ax.text(left + row["width"] / 2, bottom + row["height"] / 2, f"{int(row['Quantites vendues'])}", 
ha='center', va='center', fontsize=10, color="black", fontweight="bold")
bottom += row["height"]

left += product_width

# Ajout des labels des produits sous l'axe X
for produit, position in product_positions.items():
ax.text(position, -0.08, produit, ha='center', va='top', fontsize=12, fontweight="bold", color="black", rotation=45)

# Ajout des titres et axes
#ax.set_title("Marimekko Chart - Répartition des Ventes par Produit et Segment", fontsize=14, fontweight="bold")
ax.set_xlabel("Produits (Largeur proportionnelle aux ventes totales)", fontsize=12, labelpad=20)
ax.set_ylabel("Proportion des Ventes (Hauteur = Quantités vendues)", fontsize=12)

# Suppression des ticks pour rendre la visualisation plus propre
ax.set_xticks([])
ax.set_yticks([])

# Ajout d'une légende pour les segments en haut à gauche
handles = [plt.Rectangle((0, 0), 1, 1, color=color, edgecolor="black") for color in segment_colors.values()]
ax.legend(handles, segment_colors.keys(), title="Segments", loc="upper left", bbox_to_anchor=(-0.05, 1.15))

# Affichage
plt.show()

Heatmap

#*****************************************************************************************************
# Visuel Heatmap 
#*****************************************************************************************************

# Le code suivant, qui crée un dataframe et supprime les lignes dupliquées, est toujours exécuté et sert de préambule à votre script :

# dataset = pandas.DataFrame(Date, Quantites vendues)
# dataset = dataset.drop_duplicates()

# Importation des bibliothèques
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors

# Transformer la colonne Date en datetime et extraire le mois et le jour de la semaine
dataset["Date"] = pd.to_datetime(dataset["Date"])
dataset["Weekday"] = dataset["Date"].dt.day_name() # Jour de la semaine
dataset["Month"] = dataset["Date"].dt.month_name() # Mois

# Ordonner les jours de la semaine et les mois dans l'ordre classique
weekdays_order = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
months_order = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]

dataset["Weekday"] = pd.Categorical(dataset["Weekday"], categories=weekdays_order, ordered=True)
dataset["Month"] = pd.Categorical(dataset["Month"], categories=months_order, ordered=True)

# Agréger les quantités vendues par Mois et Jour de la semaine
df_heatmap = dataset.groupby(["Month", "Weekday"])["Quantites vendues"].sum().reset_index()

# Pivot pour la heatmap (Mois en Y, Weekdays en X)
heatmap_data = df_heatmap.pivot(index="Month", columns="Weekday", values="Quantites vendues")

# Création d'un colormap personnalisé
cmap = mcolors.LinearSegmentedColormap.from_list(
"custom_cmap", ["#0D6ABF", "#A1343C"] # Valeur min : #0D6ABF, valeur max : #A1343C
)

# Création de la Heatmap avec le colormap personnalisé
plt.figure(figsize=(12, 8))
sns.heatmap(heatmap_data, cmap=cmap, annot=True, fmt=".0f", linewidths=0.5, cbar=True)

# Labels et titre
plt.xlabel("Jour de la Semaine", fontsize=12)
plt.ylabel("Mois", fontsize=12)
#plt.title("Heatmap des Quantités Vendues par Jour de la Semaine et Mois", fontsize=14, fontweight="bold")

# Affichage
plt.show()

Radarplot

#*****************************************************************************************************
# Visuel Radarplot
#*****************************************************************************************************

# Le code suivant, qui crée un dataframe et supprime les lignes dupliquées, est toujours exécuté et sert de préambule à votre script :

# dataset = pandas.DataFrame(Produit, Quantites, Quantites totales)
# dataset = dataset.drop_duplicates()

# Importation des bibliothèques
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# Agréger les données par produit
df_radar = dataset.groupby("Produit")[["Quantites", "Quantites totales"]].sum().reset_index()

# Trier les produits pour un affichage plus clair
df_radar = df_radar.sort_values("Quantites totales", ascending=False)

# Normalisation des valeurs (échelle 0-1)
df_radar["Normalized_Quantites"] = df_radar["Quantites"] / df_radar["Quantites totales"].max()
df_radar["Normalized_Totales"] = df_radar["Quantites totales"] / df_radar["Quantites totales"].max()

# Définition des angles pour le radar plot
labels = df_radar["Produit"].tolist()
values_qte = df_radar["Normalized_Quantites"].tolist()
values_tot = df_radar["Normalized_Totales"].tolist()
angles = np.linspace(0, 2 * np.pi, len(labels), endpoint=False).tolist()

# Fermeture du graphique (première valeur répétée à la fin)
values_qte += values_qte[:1]
values_tot += values_tot[:1]
angles += angles[:1]

# Création du graphique radar
fig, ax = plt.subplots(figsize=(8, 8), subplot_kw=dict(polar=True))
plt.subplots_adjust(top=0.80) # Ajustement pour laisser de l'espace à la légende sous le titre

# Déplacer l'axe au nord**
ax.set_theta_zero_location('N') # 0° placé au nord
ax.set_theta_direction(-1) # Sens horaire

# Tracer les valeurs filtrées (quantités vendues par pays sélectionné)
ax.plot(angles, values_qte, linewidth=2, linestyle="solid", marker="o", color="#118DFF", label="Quantités Vendues (par Pays)")
ax.fill(angles, values_qte, alpha=0.3, color="#118DFF")

# Tracer les valeurs totales (quantités vendues globales)
ax.plot(angles, values_tot, linewidth=2, linestyle="dashed", marker="s", color="#E66C37", label="Quantités Totales (Fixe)")
ax.fill(angles, values_tot, alpha=0.2, color="#E66C37")

# Ajouter les étiquettes des valeurs
for i, angle in enumerate(angles[:-1]): # Exclure la répétition
ax.text(angle, values_qte[i] + 0.05, f"{df_radar['Quantites'].iloc[i]:.0f}", 
ha="center", va="center", fontsize=9, fontweight="bold", color="black")

ax.text(angle, values_tot[i] + 0.05, f"{df_radar['Quantites totales'].iloc[i]:.0f}", 
ha="center", va="center", fontsize=9, fontweight="bold", color="red")

# Configuration des axes
ax.set_xticks(angles[:-1])
ax.set_xticklabels(labels, fontsize=11, fontweight="bold", rotation=30)
ax.set_yticklabels([]) # Suppression des ticks radiaux

# Ajout d'un titre
#ax.set_title("Radar Plot - Comparaison des Quantités Vendues", fontsize=14, fontweight="bold", pad=60)

# Ajout de la légende entre le titre et la zone graphique sur une ligne
legend = ax.legend(loc="upper left", bbox_to_anchor=(0.5, 1.08), ncol=2, frameon=False, fontsize=10)

# Affichage
plt.show()

And last but not least…

Visuels de distribution des données 💥

💡Notez que la capture d’écran a été réalisé sur le portail en ligne Power BI Service… et que je n’ai rien eu à configurer, Power BI Service reconnaît le Python 😀

#*****************************************************************************************************
# Distribution des valeurs + Boxplot
#*****************************************************************************************************

import matplotlib.pyplot as plt
import seaborn as sns

# Sélection des colonnes numériques
num_cols = ["Quantites vendues", "Revenu", "COGS"]

# Création de la figure avec plusieurs sous-graphiques
fig, axes = plt.subplots(2, len(num_cols), figsize=(12, 6))

# Tracer les histogrammes et boxplots
for i, col in enumerate(num_cols):
sns.histplot(dataset[col], bins=20, ax=axes[0, i], kde=True, color="blue")
axes[0, i].set_title(f"Distribution de {col}")

sns.boxplot(y=dataset[col], ax=axes[1, i], color="red")
axes[1, i].set_title(f"Boxplot de {col}")

plt.tight_layout()
plt.show()

…Et pour aller plus loin : du Machine Learning avec Python🛸

En utilisant la bibilothèque Scikit-learn de Python, nous pouvons même lancer des mini-modèles de Machine-Learning en temps réel avec les données de notre rapport Power BI.

Voici un exemple pour détecter des anomalies potentielles dans les données de ventes en utilisant l’algorythme Local Outlier Factor.

Code Python :

#***************************************************************************************************** 
# Détection d'anomalies avec Local Outlier Factor 
#*****************************************************************************************************

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.neighbors import LocalOutlierFactor
import matplotlib.patches as mpatches

# 1 - Chargement des données depuis Power BI
df = dataset.copy()

# 2 - Sélection des colonnes et conversion en numérique
df = df[["RowIndex", "Quantites vendues", "Montant vendu"]]
df = df.apply(pd.to_numeric, errors="coerce")  # Convertir en valeurs numériques
df = df.dropna()  # Supprimer les valeurs manquantes

# 3 - Transformation en tableau numpy
X = df[["Quantites vendues", "Montant vendu"]].values  

# 4 - Entraînement du modèle LOF (Détection d’anomalies)
lof = LocalOutlierFactor(n_neighbors=50, contamination="auto")
predictions = lof.fit_predict(X)  # -1 = anomalie, 1 = normal

# 5 - Sauvegarde des résultats pour affichage du tableau
df["Anomalie"] = predictions

# 6 - Création de la figure combinée (Graphique + Tableau)
fig, axes = plt.subplots(1, 2, figsize=(14, 6), gridspec_kw={'width_ratios': [2, 1]})

# 6.1 - Graphique des anomalies (à gauche)
ax = axes[0]
colors = {1: "#118DFF", -1: "#E66C37"}  # Bleu clair = Normal, Orange = Anomalie
ax.scatter(X[:, 0], X[:, 1], c=[colors[p] for p in predictions], s=20)

# Ajout d’une légende
normal_patch = mpatches.Patch(color="#118DFF", label="Valeurs normales")
anomaly_patch = mpatches.Patch(color="#E66C37", label="Anomalies détectées")
ax.legend(handles=[normal_patch, anomaly_patch])

# Personnalisation du graphique
ax.set_facecolor("white")
ax.grid(color="#E5E5E5", linestyle="--", linewidth=0.7)
ax.set_title("Détection d'anomalies avec Local Outlier Factor", fontsize=14, color="black")
ax.set_xlabel("Quantités vendues", color="black")
ax.set_ylabel("Montant vendu", color="black")

# 6.2 - Tableau des anomalies (à droite)
ax_table = axes[1]
ax_table.axis("off")  # Masquer les axes du tableau

# Sélection des anomalies triées par Montant vendu décroissant
anomalies_df = df[df["Anomalie"] == -1].drop(columns=["Anomalie"]).sort_values(by="Montant vendu", ascending=False)

# Nombre total d’anomalies détectées
total_anomalies = anomalies_df.shape[0]

# Sélection des 10 premières anomalies pour affichage
table_data = anomalies_df.head(10).values
columns = list(anomalies_df.columns)

# Ajout d'un titre dynamique au-dessus du tableau
ax_table.text(0.5, 1.1, f"Nombre d'anomalies totales détectées : {total_anomalies}\nAffichage des 10 premières par montant décroissant",
              fontsize=12, ha="center", va="top", fontweight="bold", color="black")

# Création du tableau
table = ax_table.table(cellText=table_data, colLabels=columns, cellLoc="center", loc="center")
table.auto_set_font_size(False)
table.set_fontsize(10)

# Ajustement du tableau
table.scale(1.2, 1.2)

# 7 - Affichage final du visuel dans Power BI
plt.tight_layout()
plt.show()

Limitations des visuels Python

Bien entendu, il doit bien y avoir des limitations sinon honnêtement nous passerions tous nos visuels en Python🤓 humm. Voici les plus frustrantes :

  • Non-interactivité : Les visuels générés par un script Python sont statiques et il n’est pas possible de filtrer d’autres visuels ou de sélectionner des points. Néanmoins ils sont filtrés par les sélections utilisateurs comme le montre l’animation ci-dessous :

 

  • Limitation du volume de données : Power BI limite la quantité de données envoyée au script Python à 150 000 lignes
  • Exécution dépendante de l’environnement :
    • Pour Power BI Desktop, vous devez avoir Python installé et configuré correctement.
    • Dans Power BI Service, seuls les packages préapprouvés par Microsoft sont disponibles.
  • Temps d’exécution : les scripts Python sont plus lents à s’afficher que les visuels natifs ou custom
  • La version Mobile des rapports Power BI n’est pas prise en charge actuellement :

La liste complète des limitations est disponible ici.

Et dans Power BI Service ?

Bien que l’installation locale soit obligatoire pour Power BI Desktop, dans le service en ligne Power BI Service, vous n’avez pas besoin d’installer de Gateway personnel pour exécuter du code Python standard. Les packages supportés (comme Matplotlib et Seaborn) sont déjà reconnus par Microsoft.

Conclusion

En fin de compte, Python 🐍 et Power BI forment un duo intéressant pour concevoir des visuels ultra-personnalisés. Et pas besoin d’être un génie du développement et de coder un custom visual pour cela (dans la plupart des cas je dirais) !

  • Une grande flexibilité : si un Radarplot ou un autre visuel rare vous fait rêver, c’est possible !
  • Quelques précautions : Prévoir l’installation de Python, le respect des packages autorisés, gérer votre frustration concernant les sélections dynamiques, et la gestion du volume de données.

D’ailleurs, Microsoft ne s’arrête pas à Power BI : les notebooks Python dans Fabric et l’intégration de Python dans Excel notamment, cela montre clairement que la frontière entre Data Science et Reporting s’amenuise et qu’apprendre le langage Python sera toujours un atout précieux pour explorer, analyser et visualiser les données💡.

Alors, si vous souhaitez passer à l’étape suivante et créer des rapports réellement hors du commun, découvrez mes formations Power BI.

Cliquez ici pour accéder à la formation complète pour maîtriser Power BI

Bonne exploration !🤩

TELECHARGER LE FICHIER D’EXEMPLE

Téléchargez le fichier Power BI de ce tutoriel.

Entrez votre email pour télécharger le fichier (obligatoire)

Visuels Python dans Power BI

Voici un exemple simple de mise en place de visuels Python dans Power BI pour des visualisations avancées et uniques !
Télécharger

Envoyer le lien de téléchargement à :

Oui, je consens à recevoir la Newsletter. Je confirme avoir lu et accepté la Politique de confidentialité.

Merci d’avoir suivi cet article !!

Expérimentez les visuels Python dans vos propres rapports Power BI et laissez un commentaire sur votre expérience en bas de cet article 😉

Souscrivez à ma newsletter :

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *