使用 Apache Spark 和 Python 分析資料

在本文中,您將了解如何使用 Azure 開放資料集和 Apache Spark,來執行探索式資料分析。 本文會分析紐約市計程車資料集。 此資料可透過 Azure 開放資料集取得。 此資料集的子集包含黃色計程車車程的相關資訊:每個車程的相關資訊、開始和結束時間和位置、成本和其他有趣的屬性。

在本文章中,您將:

  • 下載並準備資料
  • 分析資料
  • 將資料視覺化

必要條件

下載並準備資料

若要開始,請下載紐約市 (NYC) 計程車資料集並準備資料。

  1. 使用 PySpark 建立筆記本。 如需指示,請參閱建立筆記本

    注意

    由於使用 PySpark 核心,因此不需要明確建立任何內容。 當您執行第一個程式碼儲存格時,系統會自動為您建立 Spark 內容。

  2. 在本文中,您會使用數個不同的程式庫來協助視覺化資料集。 若要執行這項分析,請匯入下列程式庫:

    import matplotlib.pyplot as plt
    import seaborn as sns
    import pandas as pd
    
  3. 由於未經處理資料採用 Parquet 格式,因此您可以使用 Spark 內容,將檔案直接提取到記憶體中作為 DataFrame。 使用開放資料集 API 來擷取資料並建立 Spark DataFrame。 若要推斷資料類型和結構描述,請使用 Spark DataFrame 讀取時的結構描述屬性。

    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. 讀取資料之後,請執行一些初始篩選來清除資料集。 您可以移除不需要的資料行,並新增擷取重要資訊的資料行。 此外,您也可以篩選掉資料集內的異常狀況。

    # 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")
    

分析資料

身為資料分析師,您有各種不同的工具協助您從資料中擷取見解。 在本文中的這個部分中,了解 Microsoft Fabric 筆記本中可用的一些實用工具。 在此分析中,您想要了解所選期間產生較高計程車小費的因素。

Apache Spark SQL Magic

首先,使用 Apache Spark SQL 和 magic 命令搭配 Microsoft Fabric 筆記本來執行探索性資料分析。 取得查詢之後,請使用內建 chart options 功能將結果視覺化。

  1. 在筆記本中,建立新的儲存格並複製下列程式碼。 藉由使用此查詢,您可以了解平均小費金額在選取期間變更的方式。 此查詢也可協助您識別其他有用的深入解析,包括每日最低/最高小費金額和平均票價金額。

    %%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. 查詢完成執行之後,可以切換至圖表檢視來視覺化結果。 這個範例會藉由將 day_of_month 欄位指定為索引鍵,將 avgTipAmount 指定為值,以建立折線圖。 選取項目之後,請選取 [套用] 以重新整理圖表。

將資料視覺化

除了內建的筆記本圖表選項之外,還可以使用熱門的開放原始碼程式庫來建立自己的視覺效果。 在下列範例中,使用 Seaborn 和 Matplotlib,作為常用的 Python 程式庫來呈現資料視覺效果。

  1. 若要讓開發更容易且費用較低,請縮小資料集的取樣。 請使用內建的 Apache Spark 取樣功能。 此外,Seaborn 和 Matplotlib 均需要 Pandas DataFrame 或 NumPy 陣列。 要取得 Pandas DataFrame,請使用 toPandas() 命令來轉換 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. 可以了解資料集中的小費的分佈。 使用 Matplotlib 建立色階分佈圖,以顯示小費數量和計數的分佈。 根據分佈,您可以看到小費會偏向小於或等於 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()
    

    顯示小費金額分佈的色階分佈圖螢幕擷取畫面。

  3. 接下來,請嘗試了解指定之車程的小費與星期幾之間的關聯性。 使用 Seaborn 來建立盒狀圖,以摘要說明一周內每一天的趨勢。

    # 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()
    
    

    顯示每日小費分佈的圖表。

  4. 另一個假設可能是乘客數目與計程車小費總額之間有正向關聯性。 若要確認此關聯性,請執行下列程式碼來產生盒狀圖,以說明每個乘客計數的小費分佈。

    # 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()
    

    顯示按乘客計數計算小費金額箱須圖的圖表。

  5. 最後,探索票價金額與小費金額之間的關聯性。 根據結果,您可以看到在一些觀察結果中,有人沒有給小費。 不過,整體票價與小費金額之間有正向關聯性。

    # 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()
    

    小費金額散佈圖的螢幕擷取畫面。