---
title: "Analyse et visualisation de données avec Bright Data SDK"
slug: data-analysis-and-visualization-with-bright-data-sdk
date: 2026-10-22T07:32:46+00:00
modified: 2026-10-22T07:32:49+00:00
permalink: https://brightdata.fr/blog/donnees-web/data-analysis-and-visualization-with-bright-data-sdk
type: blog
---

[ Blog ](https://brightdata.fr/blog "Blog") / [Données Web](https://brightdata.fr/blog/donnees-web)







 [Données Web](https://brightdata.fr/blog/donnees-web)

# Analyse et visualisation de données avec Bright Data SDK

Apprenez à récupérer les données de vente Zillow avec le SDK Python de Bright Data et à analyser les prix, codes postaux et rendements locatifs à San Diego avec pandas.

 11 min de lecture





 [ ![Antonello Zanini](https://media.brightdata.fr/2022/12/Antonello-Zanini-2-50x50.jpg) ](https://brightdata.com/blog/authors/antonello-zanini)

 [Antonello Zanini

Technical Writer

 ](https://brightdata.com/blog/authors/antonello-zanini)





 ![Data Analysis and Visualization with Bright Data SDK](https://media.brightdata.fr/2026/10/data-analysis-visualization-bright-data-sdk.png)





Dans ce tutoriel, vous découvrirez :

- Le scénario d’analyse de données pour explorer le marché immobilier de San Diego.
- Pourquoi le SDK Python de Bright Data simplifie l’accès à des jeux de données structurés et prêts à l’emploi.
- Comment filtrer, récupérer et exporter les données de vente immobilière Zillow.
- Comment nettoyer les données, uniformiser les unités et calculer des métriques utiles.
- Comment visualiser les prix de vente, les tendances géographiques, la précision des Zestimates et les rendements locatifs estimés.

Allons-y !

## Présentation du scénario

Imaginez que vous êtes analyste de données chargé de comprendre le marché immobilier de San Diego. Vous voulez répondre à des questions clés, telles que : *À quel prix les maisons se vendent-elles réellement ? Quels quartiers ont les prix les plus élevés au mètre carré ? Et quelle est la précision des estimations Zillow par rapport aux prix de vente finaux ?*

Pour cela, vous avez besoin d’un jeu de données récent, fiable et riche sur les maisons vendues. Pour ce type de tâches, Bright Data donne accès à un [jeu de données d’informations immobilières Zillow](/products/datasets/zillow) contenant plus de 137 millions d’enregistrements.

![Les informations de la liste de propriétés Zillow de Bright Data](https://media.brightdata.com/2026/10/s_EB3EA403DD3B88D2BEC8380CA88D5C95071EA9C6F39E4D4326D17CFEA4F67063_1792410696679_image.png)Dans les étapes suivantes, vous apprendrez à utiliser le [SDK Python de Bright Data](https://docs.brightdata.com/api-reference/SDK) pour récupérer un instantané filtré de ce jeu de données ne contenant que les enregistrements pertinents pour le scénario. Vous chargerez ensuite les données dans pandas et construirez un [Jupyter Notebook](https://jupyter.org/) avec les graphiques et analyses nécessaires pour répondre à vos questions.

En chemin, vous verrez également comment nettoyer les données, uniformiser les unités de mesure et calculer des métriques dérivées pour garantir des comparaisons justes et pertinentes entre les quartiers.

## Pourquoi utiliser le SDK Python de Bright Data ?

Bright Data est un [site de jeux de données](/blog/web-data/best-dataset-websites) de premier plan, notamment en tant que [fournisseur de données immobilières](/blog/web-data/best-real-estate-data-providers). Il propose une vaste collection de jeux de données structurés et fréquemment mis à jour, contenant des milliards d’enregistrements de données web publiquement accessibles.

Lorsque vous travaillez sur un [projet d’analyse et/ou de visualisation de données](/blog/web-data/analysis-with-python), la première étape consiste à obtenir les données dont vous avez besoin. Il existe deux approches principales :

- **Collecter les données à la demande** : Créez et exécutez des workflows de scraping web pour extraire les informations dont vous avez besoin directement depuis les sites web.
- **Utiliser des jeux de données existants** : Obtenez des jeux de données filtrés et déjà collectés, prêts pour l’analyse.

Le SDK Python de Bright Data prend en charge ces deux approches. Il fournit une interface Python simplifiée et typée pour accéder aux [solutions de collecte de données web de Bright Data](/products) et propose des méthodes pratiques pour récupérer des jeux de données structurés directement depuis la [marketplace Bright Data](/products/datasets).

Pour plus d’informations, consultez les ressources suivantes :

- [*Documentation du SDK Python*](https://docs.brightdata.com/api-reference/SDK)
- [*Dépôt du SDK Python*](https://github.com/brightdata/sdk-python)
- [*Découvrez le SDK Python de Bright Data : scraper, rechercher et obtenir des données web*](/blog/ai/bright-data-python-sdk)

## Récupérer les données pour l’analyse et la visualisation

Suivez les étapes ci-dessous pour démarrer votre projet d’analyse et de visualisation de données, en commençant par la récupération des données.

### Prérequis

Assurez-vous d’avoir :

- [Python 3.10+](https://www.python.org/downloads/) installé sur votre machine locale.
- Un [compte Bright Data](/cp/start) avec une clé API configurée. Consultez [comment obtenir votre clé API Bright Data](https://docs.brightdata.com/api-reference/authentication#how-do-i-generate-a-new-api-key).

Exécutez la commande suivante pour installer les packages Python utilisés tout au long de ce guide :

```none
pip install brightdata-sdk jupyter pandas numpy matplotlib seaborn plotly
```

Ces bibliothèques fournissent les outils nécessaires pour accéder aux jeux de données Bright Data, manipuler et analyser les données, et gérer les visualisations dans un Jupyter Notebook.

Pour authentifier le SDK Python de Bright Data, définissez votre clé API dans la variable d’environnement `BRIGHTDATA_API_KEY`. Sur macOS ou Linux, exécutez :

```none
export BRIGHTDATA_API_KEY="<YOUR_BRIGHT_DATA_API_KEY>"
```

Sur Windows, exécutez la commande suivante dans PowerShell :

```none
$env:BRIGHTDATA_API_KEY="<YOUR_BRIGHT_DATA_API_KEY>"
```

Remplacez `<YOUR_BRIGHT_DATA_API_KEY>` par votre clé API Bright Data réelle.

Pour simplifier, nous supposerons que vous avez déjà un projet Python local avec un [Jupyter Notebook configuré](https://jupyter.org/install).

### Obtenir les données cibles

Les données d’intérêt proviennent du [jeu de données d’informations de listing immobilier Zillow](/cp/datasets/browse/gd_lfqkr8wm13ixtbd8f5) sur Bright Data.

Dans ce scénario, supposez que vous vous intéressez uniquement aux propriétés vendues à San Diego au cours de l’année écoulée.

Dans votre projet Python, créez un script qui utilise le SDK Bright Data pour demander un instantané de jeu de données avec vos filtres choisis, attendre que l’instantané soit disponible, et exporter les enregistrements résultants :

```none
import asyncio
from datetime import date, timedelta
from brightdata import BrightDataClient
from brightdata.datasets import export

async def main():
    # Récupérer la date actuelle
    today = date.today()
    # Calculer le début de la fenêtre de ventes d'intérêt (année écoulée)
    one_year_ago = today - timedelta(days=365)

    # Définir les filtres que chaque maison retournée doit respecter
    filters = {
        "operator": "and",
        "filters": [
            {
                # Garder uniquement les maisons à San Diego
                "name": "city",
                "operator": "=",
                "value": "San Diego",
            },
            {
                # Garder uniquement les maisons en Californie
                "name": "state",
                "operator": "=",
                "value": "CA",
            },
            {
                # Garder uniquement les annonces vendues
                "name": "homeStatus",
                "operator": "includes",
                "value": "SOLD",
            },
            {
                # Garder uniquement les ventes de l'année écoulée
                "name": "dateSold",
                "operator": ">=",
                "value": one_year_ago.isoformat(),
            },
        ],
    }

    async with BrightDataClient() as client:
        # Demander jusqu'à 1 000 enregistrements du jeu de données filtré
        snapshot_id = await client.datasets.zillow_properties(
            filter=filters,
            records_limit=1000,
        )

        # Attendre que l'instantané soit terminé et télécharger les enregistrements
        data = await client.datasets.zillow_properties.download(
            snapshot_id,
            timeout=600 # Attendre jusqu'à 10 minutes
        )

        # Confirmer le nombre d'enregistrements téléchargés
        print(f"Downloaded {len(data)} records")

        # Enregistrer les enregistrements dans un fichier CSV
        export(data, "properties.csv")

if __name__ == "__main__":
    asyncio.run(main())
```

Le script ci-dessus demande de manière asynchrone un instantané de jeu de données, attend jusqu’à 10 minutes pour l’achèvement, télécharge les enregistrements, indique le nombre récupéré, et les exporte vers `properties.csv`, prêt pour l’analyse dans pandas.

Il utilise le SDK Bright Data pour récupérer les enregistrements de propriétés Zillow correspondant aux filtres spécifiés : maisons à San Diego, Californie, vendues au cours des 365 derniers jours. En coulisses, le SDK appelle l’[API de filtrage de Bright Data](https://docs.brightdata.com/api-reference/marketplace-dataset-api/filter-dataset), qui vous permet d’obtenir des instantanés filtrés des jeux de données Bright Data.

Gardez à l’esprit que la limite d’enregistrements est fixée à 1 000, mais vous pouvez l’ajuster à n’importe quel nombre adapté à vos besoins. Vous pouvez également ajouter de nouveaux filtres ou modifier ceux existants pour affiner le jeu de données et ne récupérer que les enregistrements pertinents pour votre analyse.

**Remarque** : La fonction utilitaire `export()` détecte le format de sortie à partir de l’extension du fichier, ainsi `.csv` produit un fichier CSV. D’autres exports de données pris en charge incluent JSON, NDJSON et JSONL.

### Explorer le jeu de données récupéré

Exécutez le script de récupération des données. Un fichier `properties.csv` apparaîtra dans le répertoire de votre projet :

![Le fichier «properties.csv» produit via le SDK Python de Bright Data](https://media.brightdata.com/2026/10/s_EB3EA403DD3B88D2BEC8380CA88D5C95071EA9C6F39E4D4326D17CFEA4F67063_1792413740198_image.png)Ouvrez le fichier, et vous remarquerez les 1 000 enregistrements de propriétés Zillow retournés au format CSV structuré. Chaque enregistrement contient environ 140 colonnes. Les plus pertinentes sont :

**Colonne****Description**`zipcode`, `latitude`, `longitude`Localisation de la maison`homeType`Type de propriété, tel que `SINGLE_FAMILY` ou `CONDO``bedrooms`, `bathrooms`Nombre de chambres et de salles de bain`price`Prix de vente en USD`livingAreaValue`, `livingAreaUnits`Surface intérieure et son unité`lotAreaValue`, `lotAreaUnits`Taille du terrain, en pieds carrés ou en acres`yearBuilt`Année de construction`dateSoldString`Date de vente (`AAAA-MM-JJ`)`daysOnZillow`Durée de publication de l’annonce`zestimate`, `rentZestimate`Valeur estimée et loyer mensuel estimé par Zillow`taxAssessedValue`Valeur utilisée pour les impôts fonciersDécouvrez-les toutes dans la [section «Dictionnaire»](/cp/datasets/browse/gd_lfqkr8wm13ixtbd8f5?tab=dictionary) de la page du panneau de contrôle Bright Data pour le jeu de données de listing immobilier Zillow :

![La section «Dictionnaire» du jeu de données de listing immobilier Zillow](https://media.brightdata.com/2026/10/s_EB3EA403DD3B88D2BEC8380CA88D5C95071EA9C6F39E4D4326D17CFEA4F67063_1792413624491_image.png)Mission accomplie ! Vous disposez maintenant des données brutes et structurées.

Ensuite, vous apprendrez à les nettoyer et à les préparer pour l’analyse et la visualisation. Puis, vous définirez plus de 10 scénarios pour explorer le marché immobilier de San Diego et répondre à vos questions clés sur les prix de vente des maisons, l’accessibilité des quartiers et la précision des estimations Zillow.

## Préparer les données pour l’analyse et la visualisation

Maintenant que vous avez récupéré le jeu de données, ouvrez votre notebook et préparez le jeu de données pour l’analyse. Dans une cellule dédiée, effectuez les tâches suivantes :

1. Importez les bibliothèques nécessaires pour la manipulation de données, l’analyse statistique et la visualisation.
2. Configurez les paramètres de traçage des données.
3. Chargez le jeu de données en important `properties.csv` dans un DataFrame pandas.
4. Nettoyez et uniformisez les données en gérant les valeurs manquantes, en corrigeant les types de données et en convertissant les champs dans des formats cohérents.
5. Créez des variables supplémentaires pour permettre une analyse, des comparaisons et des visualisations plus efficaces.

Réalisez ces étapes avec :

```none
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
from matplotlib.ticker import FuncFormatter
from IPython.display import display

# Afficher les prix de l'axe sous forme de nombres complets, par exemple 1 000 000
usd_fmt = FuncFormatter(lambda x, _: f"{x:,.0f}")

# Utiliser un style de grille épuré pour tous les graphiques
sns.set_theme(style="whitegrid")

# Facteur de conversion des pieds carrés en mètres carrés
SQFT_TO_M2 = 0.092903
# Facteur de conversion des acres en pieds carrés
ACRE_TO_SQFT = 43560
# Ignorer les codes postaux avec moins de ventes que ce seuil
MIN_SALES = 3

# Formater les colonnes d'un DataFrame sous forme de texte, puis l'afficher sous forme de tableau
def show_table(frame, formats, title=""):
    # Travailler sur une copie pour laisser les données d'origine inchangées
    out = frame.copy()
    # Appliquer chaque format à sa colonne, en affichant les valeurs manquantes sous forme de tiret
    for col, fmt in formats.items():
        out[col] = out[col].map(lambda v, f=fmt: f.format(v) if pd.notna(v) else "-")
    # Afficher un titre au-dessus du tableau si un titre est fourni
    if title:
        print(title)
    # Afficher le tableau formaté
    display(out)

# Charger le CSV, en conservant les codes postaux sous forme de texte
df = pd.read_csv("properties.csv", dtype={"zipcode": str})

# Lister les colonnes qui doivent être des nombres
numeric_cols = ["price", "bedrooms", "bathrooms", "livingAreaValue", "lotAreaValue",
                "yearBuilt", "daysOnZillow", "zestimate", "rentZestimate",
                "taxAssessedValue", "latitude", "longitude"]
# Convertir ces colonnes en nombres, en transformant les valeurs invalides en NaN
df[numeric_cols] = df[numeric_cols].apply(pd.to_numeric, errors="coerce")

# Compléter les codes postaux à 5 chiffres
df["zipcode"] = df["zipcode"].str.zfill(5)
# Convertir le texte de la date de vente en datetime
df["dateSold"] = pd.to_datetime(df["dateSoldString"])

# Trouver les lignes où la surface habitable est en pieds carrés
is_sqft = df["livingAreaUnits"].eq("Square Feet")
# Convertir les pieds carrés en m², et laisser NaN pour les autres unités
df["living_area_m2"] = np.where(is_sqft, df["livingAreaValue"] * SQFT_TO_M2, np.nan)

# Convertir les tailles de terrain en pieds carrés, qu'elles soient en acres ou déjà en pieds carrés
lot_sqft = np.where(df["lotAreaUnits"].eq("Acres"),
                    df["lotAreaValue"] * ACRE_TO_SQFT,
                    df["lotAreaValue"])
# Convertir la taille du terrain en mètres carrés
df["lot_m2"] = lot_sqft * SQFT_TO_M2

# Supprimer les lignes sans prix de vente valide
df = df[df["price"] > 0].copy()
# Calculer le prix de vente par mètre carré
df["price_per_m2"] = df["price"] / df["living_area_m2"]
# Calculer l'écart entre le prix de vente et le Zestimate en pourcentage
df["zestimate_error_pct"] = ((df["price"] - df["zestimate"])
                             / df["zestimate"].where(df["zestimate"] > 0) * 100)
# Calculer le loyer annuel en pourcentage du prix de vente
df["rent_yield_pct"] = df["rentZestimate"] * 12 / df["price"] * 100
# Regrouper les prix en tranches, étiquetées avec des nombres complets en USD
df["price_band"] = pd.cut(df["price"], bins=[0, 500_000, 1_000_000, 1_500_000, np.inf],
                          labels=["<500,000", "500,000-1,000,000",
                                  "1,000,000-1,500,000", ">1,500,000"])
# Regrouper les maisons par époque de construction
df["age_band"] = pd.cut(df["yearBuilt"], bins=[0, 1949, 1979, 1999, np.inf],
                        labels=["<1950", "1950-1979", "1980-1999", "2000+"])

# Résumer le nombre de maisons et de codes postaux dans le jeu de données nettoyé
print(f"{len(df)} sold homes across {df['zipcode'].nunique()} ZIP codes")

# Aperçu des colonnes clés avec les prix et surfaces formatés
show_table(
    # Sélectionner les colonnes clés pour l'aperçu
    df[["zpid", "streetAddress", "zipcode", "homeType", "bedrooms", "bathrooms",
        "price", "living_area_m2", "dateSold"]].head(),
    # Formater les prix en nombres complets et les surfaces avec une décimale
    formats={"price": "{:,.0f}", "living_area_m2": "{:,.1f} m²"},
    title="Sample of sold homes",
)
```

Exécutez-la, et vous obtiendrez ce résultat :

![Un échantillon du nouveau DataFrame pandas source](https://media.brightdata.com/2026/10/s_EB3EA403DD3B88D2BEC8380CA88D5C95071EA9C6F39E4D4326D17CFEA4F67063_1792414818351_image.png)Notamment, la cellule ci-dessus se charge de :

- **Normaliser les unités de mesure** : Les surfaces habitables et les tailles de terrain sont converties en mètres carrés, afin que chaque métrique basée sur la taille utilise la même unité.
- **Gérer les valeurs manquantes** : Les erreurs de Zestimate ne sont calculées que lorsque le Zestimate est supérieur à zéro, ce qui évite une division par zéro.
- **Ajouter des champs dérivés** : Le prix par m², le rendement locatif, les tranches de prix et les tranches d’âge sont ajoutés comme colonnes pour simplifier la visualisation des données.

Fantastique ! Vous êtes prêt à passer à l’analyse et à la visualisation des données.

## Analyse et visualisation

Ici, vous découvrirez plus de 10 façons pratiques d’examiner et de visualiser le jeu de données, révélant des tendances et des informations sur le marché immobilier de San Diego. Chaque section comprend un bref aperçu, le code de la cellule, le résultat obtenu et une interprétation des conclusions.

### Distribution des prix de vente

**Description** : Explorez où se situent la plupart des prix de vente, avec la médiane marquée pour voir à quel point le marché est asymétrique.

**Cellule** :

```none
plt.figure(figsize=(10, 6))

# Tracer un histogramme des prix avec une courbe de densité lissée
sns.histplot(df["price"], bins=30, kde=True, color="steelblue")

# Calculer le prix de vente médian
median = df["price"].median()

# Tracer une ligne rouge en pointillés à la médiane, étiquetée avec le nombre complet
plt.axvline(median, color="red", linestyle="--", label=f"Median: {median:,.0f} USD")
# Afficher les prix de l'axe x sous forme de nombres complets
plt.gca().xaxis.set_major_formatter(usd_fmt)

plt.title("Distribution of Sold Prices in San Diego")
plt.xlabel("Sold price (USD)")
# Supprimer le passage automatique sur l'axe x
plt.xlim(left=0)
plt.ylabel("Number of homes")
plt.legend()
plt.show()
```

**Résultat** :

![Distribution des prix de vente à San Diego](https://media.brightdata.com/2026/10/s_EB3EA403DD3B88D2BEC8380CA88D5C95071EA9C6F39E4D4326D17CFEA4F67063_1792415362648_image.png)**Commentaire** : La plupart des ventes se concentrent entre environ 500 000 et 1 500 000 USD, avec un pic près de 750 000 USD, tandis que la médiane de 950 000 USD est plus élevée. Une longue traîne atteint près de 9 500 000 USD. La distribution est asymétrique à droite, ce qui tire la moyenne au-dessus de la médiane.

### Prix médian par type de maison

**Description** : Comparez le prix de vente médian et moyen entre les types de propriétés pour voir quels types de maisons dominent le marché.

**Cellule** :

```none
# Grouper les ventes par type de propriété et calculer les statistiques récapitulatives
by_type = (df.groupby("homeType")
             # Compter les maisons, et prendre le prix médian et moyen pour chaque type
             .agg(homes=("zpid", "count"),
                  median_price=("price", "median"),
                  mean_price=("price", "mean"))
             # Trier les types du prix médian le plus élevé au plus bas
             .sort_values("median_price", ascending=False))

show_table(by_type.reset_index(),
           formats={"median_price": "{:,.0f}", "mean_price": "{:,.0f}"},
           title="Sold price by home type (USD)")

plt.figure(figsize=(10, 6))
sns.barplot(data=by_type.reset_index(), x="homeType", y="median_price", color="steelblue")
plt.gca().yaxis.set_major_formatter(usd_fmt)
plt.xticks(rotation=30)
plt.title("Median Sold Price by Home Type")
plt.xlabel("Home type")
plt.ylabel("Median price (USD)")
plt.show()
```

**Résultat** :

![Prix de vente médian par type de maison](https://media.brightdata.com/2026/10/s_EB3EA403DD3B88D2BEC8380CA88D5C95071EA9C6F39E4D4326D17CFEA4F67063_1792415894207_image.png)**Commentaire** : Les maisons unifamiliales constituent la référence la plus fiable, avec une médiane de 1 249 500 USD sur 526 ventes. Les médianes des multi-familiales et des terrains semblent plus élevées, mais reposent sur beaucoup moins de ventes (65 et 3), tandis que les maisons préfabriquées sont les moins chères à 205 750 USD, et les condos se situent à 622 500 USD.

### Codes postaux les plus chers selon le prix de vente médian

**Description** : Classez les 15 codes postaux les plus chers selon le prix de vente médian. Les codes postaux avec très peu de ventes sont exclus pour éviter des médianes trompeuses.

**Cellule** :

```none
# Grouper les ventes par code postal et calculer le nombre de ventes et le prix médian
zip_stats = (df.groupby("zipcode")
               .agg(sales=("zpid", "count"), median_price=("price", "median"))
               # Supprimer les codes postaux avec trop peu de ventes
               .query("sales >= @MIN_SALES")
               # Trier du plus cher au moins cher
               .sort_values("median_price", ascending=False)
               # Garder uniquement le top 15
               .head(15)
               # Remettre l'index du code postal en colonne
               .reset_index())

show_table(zip_stats,
           formats={"median_price": "{:,.0f}"},
           title=f"Top 15 ZIP codes by median sold price (min. {MIN_SALES} sales)")

plt.figure(figsize=(10, 7))
sns.barplot(data=zip_stats, x="median_price", y="zipcode", color="steelblue")
plt.gca().xaxis.set_major_formatter(usd_fmt)
plt.title(f"Top 15 ZIP Codes by Median Sold Price (min. {MIN_SALES} sales)")
plt.xlabel("Median price (USD)")
plt.ylabel("ZIP code")
plt.show()
```

**Résultats** :

![Tableau des 15 meilleurs codes postaux par prix de vente médian (min. 3 ventes)](https://media.brightdata.com/2026/10/s_EB3EA403DD3B88D2BEC8380CA88D5C95071EA9C6F39E4D4326D17CFEA4F67063_1792416144347_image.png)![Top 15 des codes postaux par prix de vente médian (min. 3 ventes)](https://media.brightdata.com/2026/10/s_EB3EA403DD3B88D2BEC8380CA88D5C95071EA9C6F39E4D4326D17CFEA4F67063_1792416054205_image.png)**Commentaire** : 92130, 92109 et 92106 sont en tête, avec des médianes d’au moins 1 800 000 USD. 92118 (Coronado) a la médiane la plus élevée, supérieure à 3 300 000 USD, mais trop peu de ventes pour être classé. 92106 repose sur seulement 17 ventes, sa position pourrait donc évoluer.

### Carte des lieux de vente des maisons

**Description** : Tracez chaque vente sur une carte, colorée selon le prix de vente, pour voir où se situent les maisons les plus chères.

**Cellule** :

```none
# Copier les données d'origine
map_df = df.copy()

for col in ["latitude", "longitude", "price"]:
    map_df[col] = pd.to_numeric(map_df[col], errors="coerce")

# Garder les lignes avec des coordonnées et prix de vente valides
map_df = map_df.dropna(subset=["latitude", "longitude", "price"])

fig = px.scatter_map(
    map_df,
    lat="latitude",
    lon="longitude",
    color="price",
    hover_name="streetAddress",
    hover_data={
        "zipcode": True,
        "homeType": True,
        "bedrooms": True,
        "price": ":,.0f",
        "latitude": False,
        "longitude": False,
    },
    labels={
        "price": "Sold price (USD)",
    },
    color_continuous_scale="Viridis",

    center={"lat": 32.8157, "lon": -117.1611},
    zoom=8.8,
    height=650,
    map_style="open-street-map",
    title="Where Homes Sold in San Diego (color = sold price in USD)",
)

fig.show(renderer="notebook")

# Définir les seuils géographiques
longitude_cutoff = -117.2
latitude_cutoff = 32.8

# Diviser les propriétés en groupes ouest et est
west = geo_df[geo_df["longitude"] < longitude_cutoff]
east = geo_df[geo_df["longitude"] >= longitude_cutoff]

# Diviser les propriétés en groupes nord et sud
north = geo_df[geo_df["latitude"] >= latitude_cutoff]
south = geo_df[geo_df["latitude"] < latitude_cutoff]

# Afficher les prix médians et les tailles d'échantillon
print("WESTERN VS. EASTERN PROPERTIES")
print("-" * 40)
print(f"West of longitude {longitude_cutoff}:")
print(f"  Median sold price: ${west['price'].median():,.0f}")
print(f"  Number of properties: {len(west):,}")

print(f"\nEast of or at longitude {longitude_cutoff}:")
print(f"  Median sold price: ${east['price'].median():,.0f}")
print(f"  Number of properties: {len(east):,}")

print("\nNORTHERN VS. SOUTHERN PROPERTIES")
print("-" * 40)
print(f"North of or at latitude {latitude_cutoff}:")
print(f"  Median sold price: ${north['price'].median():,.0f}")
print(f"  Number of properties: {len(north):,}")

print(f"\nSouth of latitude {latitude_cutoff}:")
print(f"  Median sold price: ${south['price'].median():,.0f}")
print(f"  Number of properties: {len(south):,}")
```

**Résultats** :

![Où les maisons se sont vendues à San Diego](https://media.brightdata.com/2026/10/s_EB3EA403DD3B88D2BEC8380CA88D5C95071EA9C6F39E4D4326D17CFEA4F67063_1792416251686_image.png)![Propriétés ouest vs est et propriétés nord vs sud](https://media.brightdata.com/2026/10/s_EB3EA403DD3B88D2BEC8380CA88D5C95071EA9C6F39E4D4326D17CFEA4F67063_1792416510933_image.png)**Commentaire** : Les maisons à l’ouest de la longitude -117.2 ont une médiane d’environ 1 380 000 USD, contre 900 000 USD à l’intérieur des terres. Les ventes au nord (médiane de 1 165 000 USD) sont bien plus chères que celles au sud (850 000 USD).

### Prix au m² par code postal

**Description** : Comparez la dispersion du prix au mètre carré parmi les 10 codes postaux ayant le plus de ventes.

**Cellule** :

```none
# Trouver les 10 codes postaux avec le plus de ventes
top_zips = df["zipcode"].value_counts().head(10).index
# Garder les ventes de ces codes postaux ayant un prix au m² valide
zip_m2 = df[df["zipcode"].isin(top_zips)].dropna(subset=["price_per_m2"])
# Ordonner les codes postaux par leur prix médian au m², du plus élevé au plus bas
order = (zip_m2.groupby("zipcode")["price_per_m2"]
               # Prendre le prix médian au m² pour chaque code postal
               .median()
               # Trier du plus élevé au plus bas
               .sort_values(ascending=False)
               # Garder les codes postaux dans cet ordre
               .index)

plt.figure(figsize=(12, 6))
sns.boxplot(data=zip_m2, x="zipcode", y="price_per_m2", order=order,
            hue="zipcode", legend=False, palette="Set2", showfliers=False)
plt.gca().yaxis.set_major_formatter(usd_fmt)
plt.title("Sold Price per m² in the 10 Most Active ZIP Codes")
plt.xlabel("ZIP code")
plt.ylabel("Price per m² (USD)")
plt.show()
```

**Résultat** :

![Prix de vente par m² dans les 10 codes postaux les plus actifs](https://media.brightdata.com/2026/10/s_EB3EA403DD3B88D2BEC8380CA88D5C95071EA9C6F39E4D4326D17CFEA4F67063_1792416932333_image.png)**Commentaire** : 92109 a le prix médian au m² le plus élevé (environ 10 500 USD) et la plus grande dispersion. 92154 est le moins cher, à environ 4 900 USD.

### Prix au m² vs surface habitable par code postal pour les maisons unifamiliales

**Description** : Vérifiez si les maisons unifamiliales plus grandes se vendent moins cher au mètre carré selon le code postal.

**Cellule** :

```none
# Garder uniquement les maisons unifamiliales avec un prix au m² et une surface habitable
d = df[
    (df["homeType"] == "SINGLE_FAMILY")
].dropna(subset=["price_per_m2", "living_area_m2"]).copy()

# Garder les 10 codes postaux les plus actifs comme groupes distincts et mettre le reste dans «Other»
d["zip_group"] = np.where(d["zipcode"].isin(top_zips), d["zipcode"], "Other")

zip_order = list(top_zips) + ["Other"]

fig = px.scatter(
    d,
    x="living_area_m2",
    y="price_per_m2",
    facet_col="zip_group",
    facet_col_wrap=4,
    category_orders={"zip_group": zip_order},
    hover_data={
        "zipcode": True,
        "price": ":,.0f",
        "living_area_m2": ":,.1f",
        "zip_group": False,
    },
    labels={
        "living_area_m2": "Living area (m²)",
        "price_per_m2": "Price per m² (USD)",
        "price": "Sold price (USD)",
    },
    height=1200,
    title="Price per m² vs. Living Area for Single-Family Homes by ZIP Code",
)

fig.for_each_annotation(
    lambda a: a.update(text=a.text.split("=")[-1])
)

fig.update_xaxes(
    matches=None,
    showticklabels=True,
    showline=True,
    tickformat=",.0f",
    title_text="Living area (m²)",
)

fig.update_yaxes(
    tickformat=",.0f",
    title_text="Price per m² (USD)",
)

fig.show(renderer="notebook")
```

**Résultat** :

![Prix au m² vs surface habitable des maisons unifamiliales dans les 10 codes postaux les plus actifs, un nuage de points par code postal](https://media.brightdata.com/2026/10/s_EB3EA403DD3B88D2BEC8380CA88D5C95071EA9C6F39E4D4326D17CFEA4F67063_1792417081593_image.png)**Commentaire** : Certains codes postaux (par exemple 92154, 92126, 92103) montrent que les grandes maisons coûtent moins cher au m². 92127 fait exception, avec une tendance à la hausse. En général, la corrélation semble presque nulle, donc le quartier compte plus que la taille.

### Matrice de corrélation des caractéristiques des maisons

**Description** : Vérifiez la corrélation de Pearson entre le prix et les principales caractéristiques physiques et de l’annonce.

**Cellule** :

```none
corr_cols = {
    # Prix de vente en USD
    "price": "Price",
    # Nombre de chambres
    "bedrooms": "Bedrooms",
    # Nombre de salles de bain
    "bathrooms": "Bathrooms",
    "living_area_m2": "Living area",
    "lot_m2": "Lot size",
    # Année de construction
    "yearBuilt": "Year built",
    # Valeur estimée de Zillow
    "zestimate": "Zestimate",
    # Valeur évaluée pour les impôts
    "taxAssessedValue": "Tax assessed value",
}
# Calculer les corrélations de Pearson entre les colonnes renommées
corr = df[list(corr_cols)].rename(columns=corr_cols).corr()

plt.figure(figsize=(10, 8))
sns.heatmap(corr, annot=True, fmt=".2f", cmap="coolwarm", vmin=-1, vmax=1, linewidths=0.5)
plt.title("Correlation Matrix of Sold Home Features (Pearson)")
plt.show()
```

**Résultat** :

![Matrice de corrélation des caractéristiques des maisons vendues (Pearson)](https://media.brightdata.com/2026/10/s_EB3EA403DD3B88D2BEC8380CA88D5C95071EA9C6F39E4D4326D17CFEA4F67063_1792417332795_image.png)**Commentaire** : Le Zestimate (0,99) fonctionne presque comme une copie du prix. La surface habitable (0,79), les salles de bain (0,56) et les chambres (0,52) sont les signaux de prix les plus utiles, tandis que l’année de construction influence à peine le prix (0,11).

### Répartition des tranches de prix dans les codes postaux les plus actifs

**Description** : Montrez comment la part des ventes dans chaque tranche de prix diffère entre les 10 codes postaux les plus actifs.

**Cellule** :

```none
# Garder les ventes des 10 codes postaux les plus actifs
top_df = df[df["zipcode"].isin(top_zips)]
# Calculer le pourcentage de chaque tranche de prix au sein de chaque code postal
mix = pd.crosstab(top_df["zipcode"], top_df["price_band"], normalize="index") * 100

ax = mix.plot(kind="barh", stacked=True, figsize=(10, 6),
              colormap="RdYlGn_r", width=0.8)
ax.set_xlabel("Share of sales (%)")
ax.set_ylabel("ZIP code")
ax.set_title("Price Band Mix in the 10 Most Active ZIP Codes")
ax.legend(title="Price band (USD)", bbox_to_anchor=(1.02, 1), loc="upper left")
plt.tight_layout()
plt.show()
```

**Résultat** :

![Répartition des tranches de prix dans les 10 codes postaux les plus actifs](https://media.brightdata.com/2026/10/s_EB3EA403DD3B88D2BEC8380CA88D5C95071EA9C6F39E4D4326D17CFEA4F67063_1792417433866_image.png)**Commentaire :** Le code postal 92154 est le plus intermédiaire, avec environ 88 % des ventes entre 500 000 et 1 000 000 USD. Les codes postaux 92130, 92109 et 92127 sont majoritairement au-dessus de 1 500 000 USD. Les ventes abordables sont les plus fréquentes dans 92115, avec environ un tiers en dessous de 500 000 USD.

### Jours sur Zillow par tranche de prix

**Description** : Vérifiez si les maisons plus chères mettent plus de temps à se vendre, en utilisant les jours sur Zillow par tranche de prix.

**Cellule** :

```none
# Garder les maisons avec à la fois des jours sur le marché et une tranche de prix
d = df.dropna(subset=["daysOnZillow", "price_band"])
# Calculer la corrélation de Spearman, qui est la corrélation de Pearson sur les rangs
rho = d["price"].rank().corr(d["daysOnZillow"].rank())

plt.figure(figsize=(10, 6))
sns.boxplot(data=d, x="price_band", y="daysOnZillow", hue="price_band",
            legend=False, palette="Oranges")
plt.title(f"Days on Zillow by Price Band (Spearman ρ with price = {rho:.2f})")
plt.xlabel("Price band (USD)")
plt.ylabel("Days on Zillow")
plt.show()
```

**Résultat** :

![Jours sur Zillow par tranche de prix](https://media.brightdata.com/2026/10/s_EB3EA403DD3B88D2BEC8380CA88D5C95071EA9C6F39E4D4326D17CFEA4F67063_1792417871588_image.png)**Commentaire** : Les jours sur Zillow varient à peine selon le prix (Spearman ρ = -0,02). Le temps de publication médian reste entre environ 140 et 170 jours dans chaque tranche, avec une large dispersion allant de près de zéro à plus de 350 jours. Le prix seul n’explique donc pas la rapidité de vente d’une maison.

### Quelle est la précision du Zestimate ?

**Description** : Mesurez l’écart entre chaque prix de vente et le Zestimate de Zillow pour voir la précision des estimations.

**Cellule** :

```none
# Garder les maisons où l'erreur a pu être calculée
d = df.dropna(subset=["zestimate_error_pct"])
median_abs_error = d["zestimate_error_pct"].abs().median()

plt.figure(figsize=(10, 6))
sns.histplot(d["zestimate_error_pct"], bins=40, kde=True, color="purple")
# Marquer l'erreur zéro, où l'estimation correspond au prix de vente
plt.axvline(0, color="black", linestyle="--")
# Se concentrer sur les erreurs entre -20% et +20%
plt.xlim(-20, 20)
plt.title(f"Sold Price vs. Zestimate (median absolute error: {median_abs_error:.1f}%)")
plt.xlabel("(Sold price - Zestimate) / Zestimate (%)")
plt.ylabel("Number of homes")
plt.show()
```

**Résultat** :

![Prix de vente vs Zestimate](https://media.brightdata.com/2026/10/s_EB3EA403DD3B88D2BEC8380CA88D5C95071EA9C6F39E4D4326D17CFEA4F67063_1792418199765_image.png)**Commentaire** : L’erreur absolue médiane n’est que de 0,3 %, donc le Zestimate est précis pour la plupart des maisons. Une poignée de ventes se situe à 20 % ou plus de l’estimation.

### Rendement locatif brut estimé par code postal

**Description** : Estimez le loyer annuel en pourcentage du prix de vente pour chaque code postal, afin de comparer les rendements locatifs.

**Cellule** :

```none
# Grouper les ventes par code postal et calculer le nombre de ventes et le rendement médian
yield_stats = (df.groupby("zipcode")
                 .agg(sales=("zpid", "count"), median_yield=("rent_yield_pct", "median"))
                 # Supprimer les codes postaux avec trop peu de ventes
                 .query("sales >= @MIN_SALES")
                 # Trier du rendement le plus élevé au plus bas
                 .sort_values("median_yield", ascending=False)
                 # Garder uniquement le top 15
                 .head(15)
                 # Remettre l'index du code postal en colonne
                 .reset_index())

show_table(yield_stats,
           formats={"median_yield": "{:.1f}%"},
           title="Top 15 ZIP codes by estimated gross rental yield")

plt.figure(figsize=(10, 7))
sns.barplot(data=yield_stats, x="median_yield", y="zipcode", color="seagreen")
plt.title("Estimated Gross Rental Yield by ZIP Code (Top 15)")
plt.xlabel("Gross yield (%) = rent Zestimate × 12 / sold price")
plt.ylabel("ZIP code")
plt.show()
```

**Résultat** :

![Top 15 des codes postaux par rendement locatif brut estimé](https://media.brightdata.com/2026/10/s_EB3EA403DD3B88D2BEC8380CA88D5C95071EA9C6F39E4D4326D17CFEA4F67063_1792418291672_image.png)![Rendement locatif brut estimé par code postal (top 15)](https://media.brightdata.com/2026/10/s_EB3EA403DD3B88D2BEC8380CA88D5C95071EA9C6F39E4D4326D17CFEA4F67063_1792418336697_image.png)**Commentaire** : Les 15 meilleurs codes postaux offrent un rendement brut entre 5,3 % et 6,7 %, une fourchette étroite. 92101 mène avec 6,7 %, suivi de 92108 (6,5 %) et 92154 (6,4 %). Comme les chiffres de loyer sont des estimations Zillow, considérez-les comme indicatifs plutôt que comme des rendements exacts.

## Pour aller plus loin

Si vous êtes intéressé par des approches similaires d’analyse et de visualisation de données web, à l’aide de graphiques ou d’IA, consultez ces guides :

- [*Filtrer un jeu de données Crunchbase et le traiter avec l’IA pour prospecter de nouveaux clients*](/blog/web-data/prospecting-new-clients-with-crunchbase-dataset)
- [*Analyse des produits les plus vendus sur Amazon*](https://www.kaggle.com/code/brightdataml/analysis-of-amazon-s-best-selling-products)
- [*Analyse de données Crunchbase pour la prospection de clients*](https://www.kaggle.com/code/brightdataml/crunchbase-data-analysis-for-client-prospecting/)

Pour approfondir cet exemple, vous pourriez ensuite [entraîner un modèle de régression pour prédire les prix de vente](https://www.kaggle.com/code/brightdataml/predicting-nvda-stock-prices-using-an-lstm), comparer les marchés immobiliers de deux villes, ou analyser les tendances historiques des prix pour des propriétés individuelles.

## Conclusion

Dans cet article, vous avez appris à utiliser le [SDK Python de Bright Data](https://docs.brightdata.com/api-reference/SDK) pour récupérer des jeux de données structurés et prêts à l’analyse, adaptés à vos besoins. Plus précisément, vous avez vu comment obtenir des données Zillow sur les maisons vendues à San Diego, nettoyer et préparer les données, et créer plus de 10 visualisations couvrant les prix de vente, les emplacements, les tailles de propriétés, les évaluations et les rendements locatifs.

Le SDK Python de Bright Data offre un accès programmatique aux produits Bright Data, y compris sa riche marketplace de jeux de données. Le SDK simplifie le processus de collecte de données, afin que vous puissiez vous concentrer sur l’analyse plutôt que sur la collecte et la préparation des données.

Récupérez vos résultats au format CSV, JSON, JSONL ou autres formats pris en charge, puis chargez-les directement dans un Jupyter Notebook pour l’analyse et la visualisation, ou transmettez-les à des outils d’IA pour une analyse plus approfondie.

Créez un compte Bright Data pour accéder aux données web publiques dont vous avez besoin pour vos projets d’analyse de données !

Contacter ventesEssai gratuit![google social icon](/wp-content/themes/brightdata/assets/images/ic_google.svg)









 Table des matières







Dedicated Scraper APIs &amp; No-Code Scrapers

Over 1000 scrapers for all popular domains. Simplify your web scraping.

[See pricing](/pricing/web-scraper "See pricing")

Just want data? Skip scraping.

Hundreds of ready-to-use datasets from all popular domains.

[See pricing](/pricing/datasets "See pricing")







 [ ](https://news.ycombinator.com/submitlink?t=Analyse+et+visualisation+de+donn%C3%A9es+avec+Bright+Data+SDK&u=https://brightdata.fr/blog/donnees-web/data-analysis-and-visualization-with-bright-data-sdk) [ ](https://www.linkedin.com/shareArticle?mini=true&title=Analyse+et+visualisation+de+donn%C3%A9es+avec+Bright+Data+SDK&url=https://brightdata.fr/blog/donnees-web/data-analysis-and-visualization-with-bright-data-sdk) [ ](http://www.reddit.com/submit?title=Analyse+et+visualisation+de+donn%C3%A9es+avec+Bright+Data+SDK&url=https://brightdata.fr/blog/donnees-web/data-analysis-and-visualization-with-bright-data-sdk)







##  Vous pourriez aussi être intéressé par

 [ ![DSPy with Bright Data](https://media.brightdata.fr/2026/10/dspy-mcp-server-web-research-agent.png) ](https://brightdata.fr/blog/ai/dspy-with-bright-data "Serveur MCP DSPy : Créer un agent de recherche web avec Bright Data")

 [AI



 ![Satyam Tripathi](https://media.brightdata.fr/2024/09/Satyam-Tripathi-50x50.png)

Satyam Tripathi

Technical Writer





### Serveur MCP DSPy : Créer un agent de recherche web avec Bright Data

Apprenez à créer un agent de recherche web DSPy avec le serveur MCP de Bright Data, puis à l’évaluer et l’optimiser avec GEPA.



 22-Oct-2026

 33 min de lecture

 ](https://brightdata.fr/blog/ai/dspy-with-bright-data)

 [ ![Cherry Studio MCP with Bright Data](https://media.brightdata.fr/2026/10/cherry-studio-mcp-bright-data-web-search-scraping.png) ](https://brightdata.fr/blog/ai/cherry-studio-with-bright-data "Tutoriel MCP Cherry Studio : Ajouter Bright Data pour la recherche web et le scraping")

 [AI



 ![Satyam Tripathi](https://media.brightdata.fr/2024/09/Satyam-Tripathi-50x50.png)

Satyam Tripathi

Technical Writer





### Tutoriel MCP Cherry Studio : Ajouter Bright Data pour la recherche web et le scraping

Découvrez comment connecter le serveur MCP de Bright Data à Cherry Studio, l’activer par assistant, et faire citer au modèle des sources web en direct.



 20-Oct-2026

 24 min de lecture

 ](https://brightdata.fr/blog/ai/cherry-studio-with-bright-data)

 [ ![Bright Data CLI vs Bright Data Python SDK](https://media.brightdata.fr/2026/10/bright-data-cli-vs-python-sdk.png) ](https://brightdata.fr/blog/comparaison/bright-data-cli-vs-python-sdk "Bright Data CLI vs Bright Data Python SDK : choisir le bon outil pour les données web")

 [Comparaison



 ![Antonello Zanini](https://media.brightdata.fr/2022/12/Antonello-Zanini-2-50x50.jpg)

Antonello Zanini

Technical Writer





### Bright Data CLI vs Bright Data Python SDK : choisir le bon outil pour les données web

Le CLI de Bright Data convient aux workflows terminal et aux agents IA, tandis que le SDK Python convient aux pipelines. Découvrez leur comparaison sur des tâches de scraping courantes.



 20-Oct-2026

 18 min de lecture

 ](https://brightdata.fr/blog/comparaison/bright-data-cli-vs-python-sdk)
