Analyser les données avec Apache Spark et Python

Dans ce tutoriel, vous découvrirez comment effectuer une analyse exploratoire des données à l’aide d’Azure Open Datasets et d’Apache Spark.

Nous analyserons en particulier le jeu de données New York City (NYC) Taxi. Les données sont disponibles dans Azure Open Datasets. Ce sous-ensemble du jeu de données contient des données sur les courses de taxis jaunes, qui incluent des informations sur chaque course, les heures et lieux de départ et d’arrivée, le prix et d’autres attributs intéressants.

Prérequis

Télécharger et préparer les données

  1. Créez un bloc-notes à l’aide de PySpark. Pour obtenir des instructions, consultez Créer un notebook.

    Notes

    Grâce au noyau PySpark, il est inutile de créer des contextes explicitement. Le contexte Spark est créé automatiquement pour vous lorsque vous exécutez la première cellule de code.

  2. Dans ce tutoriel, nous allons utiliser différentes bibliothèques pour visualiser le jeu de données. Pour effectuer cette analyse, importez les bibliothèques suivantes :

    import matplotlib.pyplot as plt
    import seaborn as sns
    import pandas as pd
    
  3. Comme les données brutes sont au format Parquet, vous pouvez utiliser le contexte Spark pour extraire le fichier en mémoire directement en tant que DataFrame. Créez un DataFrame Spark en extrayant les données via l’API Open Datasets. Ici, nous utilisons les propriétés de schéma lors de la lecture du DataFrame Spark pour déduire les types de données et le schéma.

    from azureml.opendatasets import NycTlcYellow
    
    end_date = parser.parse('2018-06-06')
    start_date = parser.parse('2018-05-01')
    nyc_tlc = NycTlcYellow(start_date=start_date, end_date=end_date)
    nyc_tlc_pd = nyc_tlc.to_pandas_dataframe()
    
    df = spark.createDataFrame(nyc_tlc_pd)
    
  4. Une fois les données lues, nous effectuerons un premier filtrage pour nettoyer le jeu de données. Nous pourrons supprimer les colonnes inutiles et ajouter des colonnes supplémentaires qui extraient des informations importantes. En outre, nous filtrerons également les anomalies dans le jeu de données.

    # Filter the dataset 
    from pyspark.sql.functions import *
    
    filtered_df = df.select('vendorID', 'passengerCount', 'tripDistance','paymentType', 'fareAmount', 'tipAmount'\
                                    , date_format('tpepPickupDateTime', 'hh').alias('hour_of_day')\
                                    , dayofweek('tpepPickupDateTime').alias('day_of_week')\
                                    , dayofmonth(col('tpepPickupDateTime')).alias('day_of_month'))\
                                .filter((df.passengerCount > 0)\
                                    & (df.tipAmount >= 0)\
                                    & (df.fareAmount >= 1) & (df.fareAmount <= 250)\
                                    & (df.tripDistance > 0) & (df.tripDistance <= 200))
    
    filtered_df.createOrReplaceTempView("taxi_dataset")
    

Analyser des données

En tant qu’analyste de données, vous disposez d’un large éventail d’outils pour vous aider à extraire des informations à partir de ces données. Dans cette partie du didacticiel, nous allons parcourir quelques outils utiles disponibles dans les blocs-notes Microsoft Fabric. Dans cette analyse, nous souhaitons comprendre les facteurs qui donnent lieu à des pourboires plus élevés pour la période sélectionnée.

Magic SQL Apache Spark

Tout d’abord, nous effectuerons une analyse exploratoire des données par Apache Spark SQL et des commandes magiques avec le bloc-notes Microsoft Fabric. Une fois que nous avons notre requête, nous allons visualiser les résultats à l’aide de la capacité chart options intégrée.

  1. Dans votre notebook, créez une cellule et copiez le code ci-dessous. À l’aide de cette requête, nous souhaitons comprendre la façon dont les montants moyens des pourboires ont changé au cours de la période sélectionnée. Cette requête nous aidera également à identifier d’autres informations utiles, notamment le montant minimal/maximal d’un pourboire par jour et le montant moyen des tarifs.

    %%sql
    SELECT 
        day_of_month
        , MIN(tipAmount) AS minTipAmount
        , MAX(tipAmount) AS maxTipAmount
        , AVG(tipAmount) AS avgTipAmount
        , AVG(fareAmount) as fareAmount
    FROM taxi_dataset 
    GROUP BY day_of_month
    ORDER BY day_of_month ASC
    
  2. Une fois l’exécution de la requête terminée, nous pouvons visualiser les résultats en basculant sur la vue graphique. Dans cet exemple, nous allons créer un graphique en courbes en spécifiant le champ day_of_month comme clé et avgTipAmount comme valeur. Une fois que vous avez effectué les sélections, sélectionnez Appliquer pour actualiser votre graphique.

Visualiser les données

Outre les options intégrées de création de graphiques du notebook, vous pouvez utiliser des bibliothèques open source populaires pour créer vos propres visualisations. Dans les exemples suivants, nous allons utiliser Seaborn et Matplotlib. Il s’agit des bibliothèques Python couramment utilisées pour la visualisation des données.

  1. Pour faciliter le développement et le rendre moins onéreux, nous allons réduire l’échantillon de jeu de données. Nous allons utiliser la capacité intégrée d’échantillonnage Apache Spark. En outre, Seaborn et Matplotlib nécessitent un DataFrame Pandas ou un tableau NumPy. Pour obtenir un DataFrame Pandas, utilisez la commande toPandas() pour convertir notre DataFrame.

    # To make development easier, faster, and less expensive, downsample for now
    sampled_taxi_df = filtered_df.sample(True, 0.001, seed=1234)
    
    # The charting package needs a Pandas DataFrame or NumPy array to do the conversion
    sampled_taxi_pd_df = sampled_taxi_df.toPandas()
    
  2. Nous souhaitons comprendre la distribution des pourboires dans notre jeu de données. Nous allons utiliser Matplotlib pour créer un histogramme montrant la répartition de la quantité et du nombre de pourboires. Sur la base de la distribution, nous pouvons voir que les pourboires sont biaisés autour de montants inférieurs ou égaux à 10 $.

    # Look at a histogram of tips by count by using Matplotlib
    
    ax1 = sampled_taxi_pd_df['tipAmount'].plot(kind='hist', bins=25, facecolor='lightblue')
    ax1.set_title('Tip amount distribution')
    ax1.set_xlabel('Tip Amount ($)')
    ax1.set_ylabel('Counts')
    plt.suptitle('')
    plt.show()
    

    Screenshot of histogram of tips.

  3. Ensuite, nous souhaitons comprendre la relation entre les pourboires pour un trajet donné et le jour de la semaine. Utilisez Seaborn pour créer un diagramme à surfaces résumant les tendances pour chaque jour de la semaine.

    # View the distribution of tips by day of week using Seaborn
    ax = sns.boxplot(x="day_of_week", y="tipAmount",data=sampled_taxi_pd_df, showfliers = False)
    ax.set_title('Tip amount distribution per day')
    ax.set_xlabel('Day of Week')
    ax.set_ylabel('Tip Amount ($)')
    plt.show()
    
    

    Graph that shows the distribution of tips per day.

  4. Une autre hypothèse que nous pouvons faire est qu’il existe une relation positive entre le nombre de passagers et le montant total du pourboire des taxis. Pour vérifier cette relation, exécutez le code suivant pour générer un diagramme à surfaces illustrant la répartition des pourboires pour chaque nombre de passagers.

    # How many passengers tipped by various amounts 
    ax2 = sampled_taxi_pd_df.boxplot(column=['tipAmount'], by=['passengerCount'])
    ax2.set_title('Tip amount by Passenger count')
    ax2.set_xlabel('Passenger count')
    ax2.set_ylabel('Tip Amount ($)')
    ax2.set_ylim(0,30)
    plt.suptitle('')
    plt.show()
    

    Graph that shows a box whisker plot.

  5. Enfin, nous souhaitons comprendre la relation entre le montant du pourboire et le montant de la course. Sur la base des résultats, nous pouvons constater qu’il y a plusieurs observations où les gens ne donnent pas de pourboire. Cependant, nous constatons également une relation positive entre le prix global de la course et le montant du pourboire.

    # Look at the relationship between fare and tip amounts
    
    ax = sampled_taxi_pd_df.plot(kind='scatter', x= 'fareAmount', y = 'tipAmount', c='blue', alpha = 0.10, s=2.5*(sampled_taxi_pd_df['passengerCount']))
    ax.set_title('Tip amount by Fare amount')
    ax.set_xlabel('Fare Amount ($)')
    ax.set_ylabel('Tip Amount ($)')
    plt.axis([-2, 80, -2, 20])
    plt.suptitle('')
    plt.show()
    

    Screenshot of scatter plot of tip amount.