GUISGAND JAMES¶
Voici mon notebook pour le projet de datascience
Je me met dans la peau d'un data analyst pour une association de consommateur uber Je leur presente ma réponse a leur problematique: Comment optimiser les prix des ubers pour payé le moins cher possible? Problematique: Comment la localisation (ville) et le moment de la journée influencent-ils les prix des trajets Uber
- Quelle est la répartition des prix des trajets Uber ?
- Comment le prix varie-t-il selon la distance du trajet ?
- Quels sont les moments de la journée où les trajets coûtent le plus cher ?
- Y a-t-il des différences de prix entre différentes zones géographiques (New York vs villes adjacentes) ?
- Quels jours de la semaine sont les plus chers pour prendre un Ub
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import seaborn as sns
import time
import os
from geopy.distance import geodesic
from geopy.geocoders import Nominatim
from sklearn.cluster import KMeans
from datetime import datetime
from scipy.stats import zscore
from tqdm.notebook import tqdm
from sklearn.linear_model import LinearRegression
#Chargement du fichier de données Uber
file_path = "uber.csv"
uber_data = pd.read_csv(file_path)
#Affichage des premières lignes du dataset
print("🔍 Aperçu des premières lignes du dataset :")
display(uber_data.head()) # Utilisation de display() pour un meilleur rendu dans Jupyter
🔍 Aperçu des premières lignes du dataset :
Unnamed: 0 | key | fare_amount | pickup_datetime | pickup_longitude | pickup_latitude | dropoff_longitude | dropoff_latitude | passenger_count | |
---|---|---|---|---|---|---|---|---|---|
0 | 24238194 | 2015-05-07 19:52:06.0000003 | 7.5 | 2015-05-07 19:52:06 UTC | -73.999817 | 40.738354 | -73.999512 | 40.723217 | 1 |
1 | 27835199 | 2009-07-17 20:04:56.0000002 | 7.7 | 2009-07-17 20:04:56 UTC | -73.994355 | 40.728225 | -73.994710 | 40.750325 | 1 |
2 | 44984355 | 2009-08-24 21:45:00.00000061 | 12.9 | 2009-08-24 21:45:00 UTC | -74.005043 | 40.740770 | -73.962565 | 40.772647 | 1 |
3 | 25894730 | 2009-06-26 08:22:21.0000001 | 5.3 | 2009-06-26 08:22:21 UTC | -73.976124 | 40.790844 | -73.965316 | 40.803349 | 3 |
4 | 17610152 | 2014-08-28 17:47:00.000000188 | 16.0 | 2014-08-28 17:47:00 UTC | -73.925023 | 40.744085 | -73.973082 | 40.761247 | 5 |
num_rows = len(uber_data)
print("nombre ligne:" + str(num_rows))
nombre ligne:200000
- DATA CLEANING
#Suppression d'une colonne inutile si elle est présente
if 'Unnamed: 0' in uber_data.columns:
uber_data.drop(columns=['Unnamed: 0'], inplace=True)
#Conversion de la colonne datetime au bon format
uber_data['pickup_datetime'] = pd.to_datetime(uber_data['pickup_datetime'], errors='coerce')
# 📌 Extraction de nouvelles fonctionnalités temporelles
uber_data['pickup_hour'] = uber_data['pickup_datetime'].dt.hour
uber_data['pickup_day'] = uber_data['pickup_datetime'].dt.day_name()
uber_data['pickup_month'] = uber_data['pickup_datetime'].dt.month
uber_data['pickup_year'] = uber_data['pickup_datetime'].dt.year
#Suppression des trajets avec des montants de course négatifs
uber_data = uber_data[uber_data['fare_amount'] > 0]
#Nettoyage des coordonnées GPS hors de la plage valide
uber_data = uber_data[
(uber_data['pickup_longitude'].between(-180, 180)) &
(uber_data['pickup_latitude'].between(-90, 90)) &
(uber_data['dropoff_longitude'].between(-180, 180)) &
(uber_data['dropoff_latitude'].between(-90, 90))
]
#Suppression des trajets avec un nombre de passagers invalide
uber_data = uber_data[(uber_data['passenger_count'] > 0) & (uber_data['passenger_count'] <= 6)]
#Affichage du nombre de lignes après nettoyage
print(f"Nombre de lignes après nettoyage : {len(uber_data)}")
display(uber_data.head()) # Affichage des premières lignes après nettoyage
Nombre de lignes après nettoyage : 199256
key | fare_amount | pickup_datetime | pickup_longitude | pickup_latitude | dropoff_longitude | dropoff_latitude | passenger_count | pickup_hour | pickup_day | pickup_month | pickup_year | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2015-05-07 19:52:06.0000003 | 7.5 | 2015-05-07 19:52:06+00:00 | -73.999817 | 40.738354 | -73.999512 | 40.723217 | 1 | 19 | Thursday | 5 | 2015 |
1 | 2009-07-17 20:04:56.0000002 | 7.7 | 2009-07-17 20:04:56+00:00 | -73.994355 | 40.728225 | -73.994710 | 40.750325 | 1 | 20 | Friday | 7 | 2009 |
2 | 2009-08-24 21:45:00.00000061 | 12.9 | 2009-08-24 21:45:00+00:00 | -74.005043 | 40.740770 | -73.962565 | 40.772647 | 1 | 21 | Monday | 8 | 2009 |
3 | 2009-06-26 08:22:21.0000001 | 5.3 | 2009-06-26 08:22:21+00:00 | -73.976124 | 40.790844 | -73.965316 | 40.803349 | 3 | 8 | Friday | 6 | 2009 |
4 | 2014-08-28 17:47:00.000000188 | 16.0 | 2014-08-28 17:47:00+00:00 | -73.925023 | 40.744085 | -73.973082 | 40.761247 | 5 | 17 | Thursday | 8 | 2014 |
- Preparation des données
#Fonction pour calculer la distance entre deux points GPS
def haversine_distance(lat1, lon1, lat2, lon2):
return geodesic((lat1, lon1), (lat2, lon2)).km
#Calcul des distances pour chaque trajet
uber_data['distance_km'] = uber_data.apply(lambda row:
haversine_distance(row['pickup_latitude'], row['pickup_longitude'],
row['dropoff_latitude'], row['dropoff_longitude']), axis=1)
#Suppression des trajets trop courts (< 200 mètres) outliers
uber_data = uber_data[uber_data['distance_km'] > 0.2]
# 📏 Affichage du nombre de lignes après suppression des trajets courts
print(f"Nombre de lignes après filtrage des trajets courts : {len(uber_data)}")
#Sauvegarde temporaire du nombre de lignes
num_rows_tmp = len(uber_data)
display(uber_data.head())
Nombre de lignes après filtrage des trajets courts : 191878
key | fare_amount | pickup_datetime | pickup_longitude | pickup_latitude | dropoff_longitude | dropoff_latitude | passenger_count | pickup_hour | pickup_day | pickup_month | pickup_year | distance_km | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2015-05-07 19:52:06.0000003 | 7.5 | 2015-05-07 19:52:06+00:00 | -73.999817 | 40.738354 | -73.999512 | 40.723217 | 1 | 19 | Thursday | 5 | 2015 | 1.681111 |
1 | 2009-07-17 20:04:56.0000002 | 7.7 | 2009-07-17 20:04:56+00:00 | -73.994355 | 40.728225 | -73.994710 | 40.750325 | 1 | 20 | Friday | 7 | 2009 | 2.454363 |
2 | 2009-08-24 21:45:00.00000061 | 12.9 | 2009-08-24 21:45:00+00:00 | -74.005043 | 40.740770 | -73.962565 | 40.772647 | 1 | 21 | Monday | 8 | 2009 | 5.039603 |
3 | 2009-06-26 08:22:21.0000001 | 5.3 | 2009-06-26 08:22:21+00:00 | -73.976124 | 40.790844 | -73.965316 | 40.803349 | 3 | 8 | Friday | 6 | 2009 | 1.661442 |
4 | 2014-08-28 17:47:00.000000188 | 16.0 | 2014-08-28 17:47:00+00:00 | -73.925023 | 40.744085 | -73.973082 | 40.761247 | 5 | 17 | Thursday | 8 | 2014 | 4.483730 |
- ADDING LOCATION DETAILS WITH API
uber_done = True # Mettre à True pour empêcher l'exécution
if not uber_done: # Vérifie si le traitement doit être effectué
#Initialisation du géocodeur et du cache pour éviter les requêtes répétées
geolocator = Nominatim(user_agent="geoapi", timeout=10)
cache = {}
#Fonction optimisée pour récupérer les localisations avec un cache
def get_location(lat, lon):
key = (lat, lon)
if key in cache: # Retourner depuis le cache si déjà calculé
return cache[key]
try:
location = geolocator.reverse((lat, lon), exactly_one=True)
address = location.raw['address']
city = address.get('city', address.get('town', address.get('village', 'Inconnu')))
state = address.get('state', 'Inconnu')
cache[key] = pd.Series([city, state]) # Ajouter au cache
return cache[key]
except:
return pd.Series(['Inconnu', 'Inconnu'])
# Définition de la taille de traitement par lot
batch_size = 1000
#Tentative de reprise depuis un fichier déjà traité
try:
processed_data = pd.read_csv("processed_uber_data.csv")
start_index = len(processed_data)
print(f"🔄 Reprise du traitement à partir de la ligne {start_index}")
except FileNotFoundError:
processed_data = pd.DataFrame()
start_index = 0
#Traitement des données par lot
for i in range(start_index, len(uber_data), batch_size):
print(f"🚀 Traitement des lignes {i} à {i + batch_size}...")
batch = uber_data.iloc[i:i + batch_size].copy()
# Application de la fonction de géolocalisation avec cache
batch[['city', 'state']] = batch.apply(lambda row: get_location(row['pickup_latitude'], row['pickup_longitude']), axis=1)
# Sauvegarde progressive pour éviter la perte de données en cas d'interruption
batch.to_csv("processed_uber_data.csv", mode='a', header=(i == 0), index=False)
print(f"✅ Lot {i} à {i + batch_size} terminé et sauvegardé.")
# Pause pour éviter de dépasser les limites de requêtes de Nominatim
time.sleep(1)
print("🎉 Traitement terminé avec succès !")
else :
print("🎉 Traitement non effecuté, fichier déjà traité !")
#Chargement du fichier de données Uber
file_path = "processed_uber_data.csv"
uber_data = pd.read_csv(file_path)
#Affichage des premières lignes du dataset
print("⚠️ Attention : Ce fichier ne contient que la ville et l'état de départ.")
print("La fonction a pris 2 jours à s'exécuter. Ajouter les villes d'arrivée aurait doublé le temps de traitement.")
print("Aperçu des premières lignes du dataset :")
display(uber_data.head())
🎉 Traitement non effecuté, fichier déjà traité ! ⚠️ Attention : Ce fichier ne contient que la ville et l'état de départ. La fonction a pris 2 jours à s'exécuter. Ajouter les villes d'arrivée aurait doublé le temps de traitement. Aperçu des premières lignes du dataset :
key | fare_amount | pickup_datetime | pickup_longitude | pickup_latitude | dropoff_longitude | dropoff_latitude | passenger_count | pickup_hour | pickup_day | pickup_month | pickup_year | distance_km | city | state | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2015-05-07 19:52:06.0000003 | 7.5 | 2015-05-07 19:52:06+00:00 | -73.999817 | 40.738354 | -73.999512 | 40.723217 | 1 | 19 | Thursday | 5 | 2015 | 1.681111 | City of New York | New York |
1 | 2009-07-17 20:04:56.0000002 | 7.7 | 2009-07-17 20:04:56+00:00 | -73.994355 | 40.728225 | -73.994710 | 40.750325 | 1 | 20 | Friday | 7 | 2009 | 2.454363 | City of New York | New York |
2 | 2009-08-24 21:45:00.00000061 | 12.9 | 2009-08-24 21:45:00+00:00 | -74.005043 | 40.740770 | -73.962565 | 40.772647 | 1 | 21 | Monday | 8 | 2009 | 5.039603 | City of New York | New York |
3 | 2009-06-26 08:22:21.0000001 | 5.3 | 2009-06-26 08:22:21+00:00 | -73.976124 | 40.790844 | -73.965316 | 40.803349 | 3 | 8 | Friday | 6 | 2009 | 1.661442 | City of New York | New York |
4 | 2014-08-28 17:47:00.000000188 | 16.0 | 2014-08-28 17:47:00+00:00 | -73.925023 | 40.744085 | -73.973082 | 40.761247 | 5 | 17 | Thursday | 8 | 2014 | 4.483730 | City of New York | New York |
#Vérification de la différence du nombre de lignes avant et après traitement
num_rows = len(uber_data)
if (num_rows_tmp > num_rows):
print("📉 Moins de lignes dans le fichier final.")
elif (num_rows_tmp < num_rows):
print("📈 Plus de lignes dans le fichier final.")
else:
print("📊 Même nombre de lignes avant et après traitement.")
#Calcul du nombre de valeurs valides pour city et state
filled_city_count = np.sum((uber_data['city'].notna()) & (uber_data['city'] != "Inconnu"))
filled_state_count = np.sum((uber_data['state'].notna()) & (uber_data['state'] != "Inconnu"))
print(f"🏙️ Nombre de villes détectées : {filled_city_count}")
print(f"🌎 Nombre d'États détectés : {filled_state_count}")
#Vérification finale de la cohérence des données
if (num_rows_tmp == num_rows == filled_city_count == filled_state_count):
print("✅ Toutes les données sont correctes et complètes !")
#Sauvegarde du fichier final avec les coordonnées géographiques
output_file = 'uberGEOPOINTout.csv'
#Vérification que le fichier existe bien avant d'afficher le message
if (not(os.path.exists(output_file))):
uber_data.to_csv(output_file)
if (os.path.exists(output_file)):
print(f"✅ Fichier bien enregistré sous '{output_file}' ({os.path.getsize(output_file)} octets).")
uber_data = pd.read_csv(output_file)
else:
print("❌ Erreur : Le fichier n'a pas été enregistré correctement !")
else:
print(f"✅ Fichier déja enregistré sous '{output_file}' ({os.path.getsize(output_file)} octets).")
📊 Même nombre de lignes avant et après traitement. 🏙️ Nombre de villes détectées : 191830 🌎 Nombre d'États détectés : 191829 ✅ Fichier déja enregistré sous 'uberGEOPOINTout.csv' (34231481 octets).
📌 1. Répartition des prix des trajets Uber
# 📊 Distribution des prix des trajets Uber
plt.figure(figsize=(10, 5))
sns.histplot(uber_data['fare_amount'], bins=50, kde=True, color="blue")
plt.title("Répartition des prix des trajets Uber")
plt.xlabel("Prix du trajet ($)")
plt.ylabel("Nombre de trajets")
plt.show()
# 📊 Distribution des prix des trajets Uber
plt.figure(figsize=(10, 5))
sns.histplot(uber_data['fare_amount'], bins=100, kde=True, color="blue")
plt.title("Répartition des prix des trajets Uber")
plt.xlim(0, 50) # Supposons que la majorité des trajets coûtent moins de 50$
plt.xlabel("Prix du trajet ($)")
plt.ylabel("Nombre de trajets")
plt.xticks(range(0, 52, 2)) # Afficher des valeurs tous les 5$
plt.show()
# Calcul du nombre total de trajets et des trajets > 50$
pourcentage = (len(uber_data[uber_data['fare_amount'] > 50]) / len(uber_data)) * 100
# Affichage du résultat avec un arrondi à 2 décimales
print(f"📊 Nombre de trajets > 50$ : {len(uber_data[uber_data['fare_amount'] > 50])} sur {len(uber_data)} ({pourcentage:.2f}%)")
📊 Nombre de trajets > 50$ : 2362 sur 191878 (1.23%)
hourly_avg_fare = uber_data.groupby("pickup_hour")['fare_amount'].mean()
plt.figure(figsize=(20, 10))
sns.lineplot(x=hourly_avg_fare.index, y=hourly_avg_fare.values, marker="o")
plt.xlabel("Heure de la journée")
plt.ylabel("Prix moyen ($)")
plt.title("Prix moyen des trajets Uber selon l'heure de la journée")
plt.xticks(range(0, 26, 2)) # Afficher des valeurs tous les 5$
plt.show()
hourly_med_fare = uber_data.groupby("pickup_hour")['fare_amount'].median()
plt.figure(figsize=(20, 10))
sns.lineplot(x=hourly_med_fare.index, y=hourly_med_fare.values, marker="o")
plt.xlabel("Heure de la journée")
plt.ylabel("Prix médian ($)")
plt.title("Prix médian des trajets Uber selon l'heure de la journée")
plt.xticks(range(0, 26, 2)) # Afficher des valeurs tous les 5$
plt.show()
sns.scatterplot(x=uber_data['distance_km'], y=uber_data['fare_amount'], alpha=0.5)
plt.xlabel("Distance du trajet (km)")
plt.ylabel("Prix du trajet ($)")
plt.title("Relation entre distance et prix")
plt.show()
sns.scatterplot(x=uber_data['distance_km'], y=uber_data['fare_amount'], alpha=0.5)
plt.xlabel("Distance du trajet (km)")
plt.ylabel("Prix du trajet ($)")
plt.title("Relation entre distance et prix")
plt.xlim(0,30)
plt.ylim(0,100)
plt.show()
filtered_data = uber_data[
(uber_data['distance_km'] >= 0) & (uber_data['distance_km'] <= 30) &
(uber_data['fare_amount'] >= 0) & (uber_data['fare_amount'] <= 100)
]
count_low_km = len(filtered_data)
total_count = len(uber_data)
print(f"Taille de toute les courses Uber jusqu'a 30km et pour un prix en dessus de 100$ ({count_low_km})")
print(f"Taille de toute les courses Uber ({total_count})")
print(f"📊 Proximité entre cette image et ce jeux de data : ({(count_low_km/total_count) *100:.2f}%)")
Taille de toute les courses Uber jusqu'a 30km et pour un prix en dessus de 100$ (191332) Taille de toute les courses Uber (191878) 📊 Proximité entre cette image et ce jeux de data : (99.72%)
correlation = uber_data[['distance_km', 'fare_amount']].corr().iloc[0, 1]
print(f"Corélation entre distance_km et fare_amount (le prix): {correlation:.2f}")
plt.figure(figsize=(10, 6))
sns.regplot(x=uber_data['distance_km'], y=uber_data['fare_amount'], scatter_kws={'alpha':0.5}, line_kws={"color":"red"})
plt.xlabel("Distance du trajet (km)")
plt.ylabel("Prix du trajet ($)")
plt.title(f"Relation entre Distance et Prix (Corrélation: {correlation:.2f})")
plt.xlim(0, 30)
plt.ylim(0, 100)
plt.show()
short_trips = filtered_data[filtered_data['distance_km'] < 5] # Petits trajets
long_trips = filtered_data[filtered_data['distance_km'] >= 5] # Grands trajets
# Vérifier si la corrélation est plus forte pour les trajets longs
short_corr = short_trips[['distance_km', 'fare_amount']].corr().iloc[0, 1]
long_corr = long_trips[['distance_km', 'fare_amount']].corr().iloc[0, 1]
# Plot for short trips
plt.figure(figsize=(10, 6))
sns.regplot(x=short_trips['distance_km'], y=short_trips['fare_amount'], scatter_kws={'alpha':0.5}, line_kws={"color":"red"})
plt.xlabel("Distance du trajet (km)")
plt.ylabel("Prix du trajet ($)")
plt.title(f"Relation Distance-Prix pour COURTS trajets (<5km) (Corrélation: {short_corr:.2f})")
plt.xlim(0, 5)
plt.ylim(0, 50)
plt.show()
plt.figure(figsize=(10, 6))
sns.regplot(x=long_trips['distance_km'], y=long_trips['fare_amount'], scatter_kws={'alpha':0.5}, line_kws={"color":"red"})
plt.xlabel("Distance du trajet (km)")
plt.ylabel("Prix du trajet ($)")
plt.title(f"Relation Distance-Prix pour LONGS trajets (>=5km) (Corrélation: {long_corr:.2f})")
plt.xlim(5, 30)
plt.ylim(0, 100)
plt.show()
print(f"📊 Corrélation pour trajets courts (<5km) : {short_corr:.2f}")
print(f"📊 Corrélation pour trajets longs (>=5km) : {long_corr:.2f}")
Corélation entre distance_km et fare_amount (le prix): 0.03
📊 Corrélation pour trajets courts (<5km) : 0.66 📊 Corrélation pour trajets longs (>=5km) : 0.85
Q1_distance = uber_data['distance_km'].quantile(0.1)
Q9_distance = uber_data['distance_km'].quantile(0.9)
uber_data_tmp = uber_data[(uber_data['distance_km'] >= Q1_distance) & (uber_data['distance_km'] <= Q9_distance)]
print(f"Voici Q1 et Q9 distance {Q1_distance} {Q9_distance}")
Q1_fare = uber_data_tmp['fare_amount'].quantile(0.1)
Q9_fare = uber_data_tmp['fare_amount'].quantile(0.9)
uber_data_tmp = uber_data_tmp[(uber_data_tmp['fare_amount'] >= Q1_fare) & (uber_data_tmp['fare_amount'] <= Q9_fare)]
correlation = uber_data_tmp[['distance_km', 'fare_amount']].corr().iloc[0, 1]
plt.figure(figsize=(20, 12))
sns.regplot(x=uber_data_tmp['distance_km'], y=uber_data_tmp['fare_amount'], scatter_kws={'alpha':0.5}, line_kws={"color":"red"})
plt.xlabel("Distance du trajet (km)")
plt.ylabel("Prix du trajet ($)")
plt.title(f"Relation entre Distance et Prix après suppression des outliers (Corrélation: {correlation:.2f})")
plt.xlim(Q1_distance, Q9_distance)
plt.ylim(Q1_fare, Q9_fare)
plt.show()
Voici Q1 et Q9 distance 0.8484124753822319 7.183897191658822
Q9_distance = uber_data['distance_km'].quantile(0.9)
Q9_fare = uber_data['fare_amount'].quantile(0.9)
filtered_data = uber_data[(uber_data['distance_km'] >= 0) & (uber_data['distance_km'] <= Q9_distance) & (uber_data['fare_amount'] >= 0) & (uber_data['fare_amount'] <= Q9_fare)].copy()
X_filtered = filtered_data[['distance_km']].values
y_filtered = filtered_data['fare_amount'].values
model_filtered = LinearRegression()
model_filtered.fit(X_filtered, y_filtered)
X_pred = np.linspace(0, Q9_distance, 100).reshape(-1, 1) # Créer 100 valeurs entre 0 et Q9
y_pred = model_filtered.predict(X_pred)
plt.figure(figsize=(10, 6))
sns.scatterplot(x=filtered_data['distance_km'], y=filtered_data['fare_amount'], alpha=0.5, label="Données réelles")
plt.plot(X_pred, y_pred, color="red", label="Régression Linéaire")
plt.xlabel("Distance du trajet (km)")
plt.ylabel("Prix du trajet ($)")
plt.title("Régression Linéaire sur l'intervalle [0 - Q9]")
plt.xlim(0, Q9_distance)
plt.ylim(0, Q9_fare)
plt.legend()
plt.show()
# Affichage des coefficients du modèle
slope_filtered = model_filtered.coef_[0] # Pente
intercept_filtered = model_filtered.intercept_ # Ordonnée à l'origine
print(f"📊 Équation du modèle (0-Q9) : Prix = {slope_filtered:.2f} * Distance + {intercept_filtered:.2f}")
📊 Équation du modèle (0-Q9) : Prix = 1.99 * Distance + 3.92
# Assurer l'ordre des jours en anglais (pour l'analyse car j'ai pas traduis dans le dataset) et en français (pour l'affichage)
days_order = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
days_translation = {
"Monday": "Lundi",
"Tuesday": "Mardi",
"Wednesday": "Mercredi",
"Thursday": "Jeudi",
"Friday": "Vendredi",
"Saturday": "Samedi",
"Sunday": "Dimanche"
}
# Palette de couleurs pour chaque jour
palette = sns.color_palette("husl", 7)
fig, axes = plt.subplots(nrows=1, ncols=7, figsize=(20, 5), sharey=True)
for i, day in enumerate(days_order):
day_data = uber_data[uber_data["pickup_day"] == day].groupby("pickup_hour")["fare_amount"].mean()
sns.barplot(x=day_data.index, y=day_data.values, ax=axes[i], color=palette[i], alpha=0.8)
axes[i].set_title(days_translation[day], fontsize=12, fontweight="bold")
axes[i].set_xlabel("Heure de la journée", fontsize=10)
# Afficher uniquement l'axe Y sur le premier graphe pour éviter la surcharge
if i == 0:
axes[i].set_ylabel("Prix moyen (€)", fontsize=10)
else:
axes[i].set_ylabel("")
axes[i].set_xticks(range(0, 24, 2))
axes[i].set_xticklabels(range(0, 24, 2), rotation=45)
plt.suptitle("Prix moyen des trajets Uber selon l'heure et le jour de la semaine", fontsize=16, fontweight="bold")
plt.tight_layout()
plt.show()
📌 3. Quels sont les moments où les trajets coûtent le plus cher ?
# Variation du prix selon l'heure de la journée
plt.figure(figsize=(12, 6))
sns.boxplot(x=uber_data['pickup_hour'], y=uber_data['fare_amount'])
plt.title("Prix moyen des trajets en fonction de l'heure de la journée")
plt.xlabel("Heure de la journée")
plt.ylabel("Prix du trajet ($)")
#plt.ylim(0, 100) # On limite l'axe Y pour éviter les valeurs extrêmes
plt.show()
📌 4. Différences de prix entre zones géographiques
#Comparaison des prix entre différentes villes
city_avg_fare = uber_data.groupby('city')['fare_amount'].mean().sort_values(ascending=False)
plt.figure(figsize=(25, 8))
sns.barplot(x=city_avg_fare.index, y=city_avg_fare.values, hue=city_avg_fare.index, palette="coolwarm", legend=False)
plt.xticks(rotation=90)
plt.title("Prix moyen des trajets par ville")
plt.xlabel("Ville")
plt.ylabel("Prix moyen ($)")
plt.show()
Dernière et Première
image_path = "D:\m1s2\sdd\projet\images\Chestnut_Ridge.PNG"
img = mpimg.imread(image_path)
# Afficher l'image
plt.figure(figsize=(16, 12))
plt.imshow(img)
plt.axis("off") # Cacher les axes | Ne pas mettre en commentaire
plt.title("Description")
plt.show()
image_path = "D:\m1s2\sdd\projet\images\\uniondale.PNG"
img = mpimg.imread(image_path)
plt.figure(figsize=(16, 12))
plt.imshow(img)
plt.axis("off") # Cacher les axes | Ne pas mettre en commentaire
plt.title("Description")
plt.show()
# Calcul du prix médian par ville (sans suppression des outliers)
city_median_fare = uber_data.groupby('city')['fare_amount'].median().sort_values(ascending=False)
# Tracer le graphique
plt.figure(figsize=(25, 8))
sns.barplot(x=city_median_fare.index, y=city_median_fare.values, hue=city_median_fare.index, palette="coolwarm", legend=False)
plt.xticks(rotation=90)
plt.title("Prix médian des trajets par ville")
plt.xlabel("Ville")
plt.ylabel("Prix médian ($)")
plt.show()
# Calcul du prix médian par ville
city_median_fare = uber_data.groupby('city')['fare_amount'].median()
# Calcul Q1, Q3 et de l'ecart interquartille
Q1 = city_median_fare.quantile(0.25)
Q3 = city_median_fare.quantile(0.75)
IQR = Q3 - Q1
# Définition des bornes pour exclure les outliers
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# Filtrer les villes sans outliers
filtered_city_median_fare = city_median_fare[(city_median_fare >= lower_bound) & (city_median_fare <= upper_bound)]
filtered_city_median_fare = filtered_city_median_fare.sort_values(ascending=False)
#Tracer le graphique
plt.figure(figsize=(25, 8))
sns.barplot(x=filtered_city_median_fare.index, y=filtered_city_median_fare.values, hue=filtered_city_median_fare.index, palette="coolwarm", legend=False)
plt.xticks(rotation=90)
plt.title("Prix médian des trajets par ville (sans outliers)")
plt.xlabel("Ville")
plt.ylabel("Prix médian ($)")
plt.show()
📌 5. Quels jours sont les plus chers pour prendre un Uber ?
# Calcul du prix moyen par jour
day_avg_fare = uber_data.groupby('pickup_day')['fare_amount'].mean()
day_avg_fare.index = day_avg_fare.index.map(days_translation)
# Trier les jours en ordre croissant selon le prix moyen
day_avg_fare = day_avg_fare.sort_values(ascending=True)
# Tracer le graphique
plt.figure(figsize=(12, 6))
sns.barplot(x=day_avg_fare.index, y=day_avg_fare.values, hue=day_avg_fare.index, palette="viridis", legend=False)
plt.title("Prix moyen des trajets Uber selon le jour de la semaine", fontsize=14, fontweight="bold")
plt.xlabel("Jour de la semaine")
plt.ylabel("Prix moyen ($)")
plt.xticks(rotation=45)
plt.show()
📌 6. Quels prix moyen sont les plus chers pour prendre un Uber Samedi ou Mardi(par heure) ?
jours_moins_chers = day_avg_fare.index[:2] # Les 2 premiers jours de l'analyse précédente
# Filtrer les données pour ne garder que ces jours
filtered_data = uber_data[uber_data["pickup_day"].map(days_translation) .isin(jours_moins_chers)]
# Calcul du prix moyen par heure pour ces jours
hourly_fare = filtered_data.groupby(["pickup_day", "pickup_hour"])["fare_amount"].mean().reset_index()
# Traduire les jours en français
hourly_fare["pickup_day"] = hourly_fare["pickup_day"].map(days_translation)
# Tracer les graphiques pour ces jours
plt.figure(figsize=(12, 6))
sns.lineplot(data=hourly_fare, x="pickup_hour", y="fare_amount", hue="pickup_day", marker="o", palette="coolwarm")
# Titre et labels
plt.title(f"Prix moyen des trajets Uber par heure ({jours_moins_chers[0]} & {jours_moins_chers[1]})", fontsize=14, fontweight="bold")
plt.xlabel("Heure de la journée")
plt.ylabel("Prix moyen ($)")
plt.xticks(range(0, 24, 1)) # Afficher une graduation toutes les 1 heures
plt.legend(title="Jour")
plt.grid(True, linestyle="--", alpha=0.6)
# Afficher
plt.show()
state_avg_fare_per_km = uber_data.groupby('state')['fare_amount'].sum() / uber_data.groupby('state')['distance_km'].sum()
state_avg_fare_per_km = state_avg_fare_per_km.sort_values(ascending=False)
plt.figure(figsize=(14, 6))
sns.barplot(x=state_avg_fare_per_km.index, y=state_avg_fare_per_km.values, hue=state_avg_fare_per_km.index, palette="coolwarm", legend=False)
plt.xticks(rotation=45)
plt.xlabel("État")
plt.ylabel("Prix moyen par km ($)")
plt.title("Prix moyen par km pour chaque État")
plt.show()
Conclusion¶
Réponse aux questions de la problématique
- Répartition des prix des trajets Uber
Les prix des trajets Uber varient considérablement, avec une majorité de courses courtes et bon marché, mais quelques courses plus longues et coûteuses. Certaines valeurs aberrantes ont été supprimées pour affiner l’analyse.
- Variation du prix selon la distance
L’analyse de la relation entre la distance et le prix montre une corrélation modérée. La régression linéaire (Prix = 1.99 × Distance + 3.92) indique que le coût moyen par kilomètre est d’environ 2 dollars, avec un tarif de base de 3.92 dollars. Cependant, des variations existent selon d’autres facteurs comme la demande et la localisation.
- Moments de la journée où les trajets coûtent le plus cher
Les prix augmentent fortement tôt le matin (entre 4h et 6h), ce qui peut être dû à une forte demande pour les trajets vers les aéroports ou le travail. Une légère augmentation des prix est aussi visible en fin d’après-midi (14h-17h), probablement en raison des déplacements domicile-travail. Les prix sont plus bas entre 10h et 16h et en début de soirée, particulièrement entre 19h et 21h.
- Différences de prix entre différentes zones géographiques
Le prix moyen par kilomètre varie fortement selon les États. Massachusetts a le prix au kilomètre le plus élevé, suivi de New York et de la Pennsylvanie. Des États comme le Connecticut ou le New Jersey affichent des prix plus faibles.
- Jours les plus chers pour prendre un Uber
Les jours les plus chers sont globalement le vendredi et le dimanche, probablement en raison des sorties en soirée et des retours de week-end. À l’inverse, les jours les moins chers sont le mardi et le samedi. Les moments les moins chers pour prendre un Uber sont le mardi et le samedi, entre 10h et 16h ou entre 19h et 21h.
Conclusion Les prix des trajets Uber sont influencés par plusieurs facteurs : La localisation : New York et certaines villes adjacentes ont des prix plus élevés. L’heure de la journée : Les pics tarifaires sont observés tôt le matin et en fin d’après-midi. Le jour de la semaine : Les tarifs sont plus élevés en fin de semaine (vendredi-dimanche). Si vous souhaitez optimiser vos dépenses en Uber, privilégiez les trajets le mardi ou le samedi entre 10h et 16h ou entre 19h et 21h, en évitant les heures de pointe du matin et de l’après-midi.