在 Google Cloud 上使用 R 進行數據資料學作業:探索式資料分析

Last reviewed 2024-07-22 UTC

本文說明如何開始在Google Cloud上使用 R 大規模進行資料科學作業。本教學課程適合具備 RJupyter 筆記本使用經驗,且熟悉 SQL 的使用者。

本文著重於使用 Vertex AI Workbench 執行個體BigQuery 進行探索性資料分析。您可以在 GitHub 上的 Jupyter 筆記本中找到隨附程式碼。

總覽

R 是最廣泛使用的統計模型程式設計語言之一。Kaggle 擁有龐大且活躍的數據資料學家和機器學習 (ML) 專業人士社群。Comprehensive R Archive Network (CRAN) 的開放原始碼存放區中,有超過 20,000 個套件,因此 R 具備適用於所有統計資料分析應用程式、機器學習和視覺化作業的工具。R 的語法具有表達力,且資料和機器學習程式庫相當全面,因此在過去二十年來穩定成長。

身為資料科學家,您可能想瞭解如何運用 R 語言的技能,以及如何充分利用可擴充的全代管雲端服務,提升資料科學的優勢。

架構

在本逐步導覽中,您會使用 Vertex AI Workbench 執行個體做為資料科學環境,執行探索性資料分析 (EDA)。在本逐步導覽中,您會從 BigQuery (Google 的無伺服器雲端資料倉儲,具備高度擴充性與成本效益) 擷取資料,並使用 R 語言處理這些資料。分析及處理資料後,轉換後的資料會儲存在 Cloud Storage 中,以供後續可能的 ML 工作使用。這個流程如下圖所示:

資料從 BigQuery 流向 Vertex AI Workbench,並在該處使用 R 處理,然後將結果傳送至 Cloud Storage,以供進一步分析。

範例資料

本文的範例資料是 BigQuery 紐約市計程車車程資料集。這個公開資料集包含每年在紐約市發生的數百萬趟計程車行程資訊。本文使用 2022 年的資料,這些資料位於 BigQuery 的 bigquery-public-data.new_york_taxi_trips.tlc_yellow_trips_2022 資料表中。

本文著重於 EDA,以及使用 R 和 BigQuery 進行視覺化。本文中的步驟可協助您設定 ML 目標,根據行程的幾項因素預測計程車車資 (不含稅金、費用和其他額外費用)。本文不包含實際建立模型的內容。

Vertex AI Workbench

Vertex AI Workbench 是一項服務,提供整合式 JupyterLab 環境,具備下列功能:

  • 一鍵部署。只要按一下滑鼠,即可啟動預先設定最新機器學習和資料科學架構的 JupyterLab 執行個體。
  • 視需求調度資源。您可以先使用小型機器設定 (例如本文件中的 4 個 vCPU 和 16 GB 的 RAM),當資料量過大而無法在一台機器上處理時,再新增 CPU、RAM 和 GPU 來擴充。
  • Google Cloud 整合。Vertex AI Workbench 執行個體已與 BigQuery 等服務整合 Google Cloud 。這項整合功能可簡化從資料擷取到預先處理和探索的流程。
  • 即付即用計費:沒有最低費用門檻,也不需要預付任何費用,如需相關資訊,請參閱 Vertex AI Workbench 定價。此外,您還需要為筆記本中使用的 Google Cloud 資源付費 (例如 BigQuery 和 Cloud Storage)。

Vertex AI Workbench 執行個體筆記本會在深度學習 VM 映像檔上執行。本文說明如何建立搭載 R 4.3 的 Vertex AI Workbench 執行個體。

使用 R 處理 BigQuery 資料

BigQuery 不需要管理基礎架構,因此您可以專注於發掘有意義的洞察資料。您可以運用 BigQuery 豐富的 SQL 分析功能,大規模分析大量資料,並準備機器學習資料集。

如要使用 R 查詢 BigQuery 資料,可以採用開放原始碼 R 程式庫 bigrquery。bigrquery 套件在 BigQuery 基礎上提供下列抽象層級:

  • 低階 API 會在基礎 BigQuery REST API 上提供精簡的包裝函式。
  • DBI 介面會包裝低階 API,讓您使用 BigQuery 時,就像使用任何其他資料庫系統一樣。如果您想在 BigQuery 中執行 SQL 查詢,或上傳小於 100 MB 的檔案,這個層級最方便。
  • dbplyr 介面可讓您將 BigQuery 資料表視為記憶體內資料框架。如果您不想編寫 SQL,而是想讓 dbplyr 為您編寫,這個圖層最方便。

本文使用 bigrquery 的低階 API,不需 DBI 或 dbplyr。

目標

  • 建立支援 R 的 Vertex AI Workbench 執行個體。
  • 使用 bigrquery R 程式庫查詢及分析 BigQuery 資料。
  • 在 Cloud Storage 中準備及儲存機器學習資料。

費用

在本文件中,您會使用 Google Cloud的下列計費元件:

如要根據預測用量估算費用,請使用 Pricing Calculator

初次使用 Google Cloud 的使用者可能符合免費試用資格。

事前準備

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. Enable the Compute Engine API.

    Enable the API

  5. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  6. Verify that billing is enabled for your Google Cloud project.

  7. Enable the Compute Engine API.

    Enable the API

  8. 建立 Vertex AI Workbench 執行個體

    第一步是建立 Vertex AI Workbench 執行個體,供您逐步完成本導覽。

    1. 前往 Google Cloud 控制台的「Workbench」頁面。

      前往 Workbench

    2. 在「執行個體」分頁中,按一下 「建立新項目」

    3. 在「New instance」(新執行個體) 視窗中,按一下「Create」(建立)。在本逐步解說中,請保留所有預設值。

      Vertex AI Workbench 執行個體可能需要 2 到 3 分鐘才能啟動。準備就緒後,執行個體會自動列在「Notebook instances」(筆記本執行個體) 窗格中,且執行個體名稱旁會顯示「Open JupyterLab」(開啟 JupyterLab) 連結。如果幾分鐘後,清單中仍未顯示開啟 JupyterLab 的連結,請重新整理頁面。

    開啟 JupyterLab 並安裝 R

    如要在筆記本中完成導覽,您需要開啟 JupyterLab 環境、安裝 R、複製 vertex-ai-samples GitHub 存放區,然後開啟筆記本。

    1. 在執行個體清單中,按一下「Open Jupyterlab」。瀏覽器會開啟新分頁,顯示 JupyterLab 環境。

    2. 在 JupyterLab 環境中,依序點選「New Launcher」和「Launcher」分頁標籤中的「Terminal」

    3. 在終端機窗格中安裝 R:

      conda create -n r
      conda activate r
      conda install -c r r-essentials r-base=4.3.2
      

      安裝期間,每次系統提示您繼續時,請輸入 y。安裝作業可能需要幾分鐘才會完成。安裝完成後,輸出內容會類似以下內容:

      done
      Executing transaction: done
      ® jupyter@instance-INSTANCE_NUMBER:~$
      

      其中 INSTANCE_NUMBER 是指派給 Vertex AI Workbench 執行個體的專屬編號。

    4. 終端機執行完畢後,請重新整理瀏覽器頁面,然後按一下「New Launcher」(新版啟動器) ,開啟啟動器。

      「啟動器」分頁會顯示在筆記本或控制台中啟動 R 的選項,以及建立 R 檔案的選項。

    5. 按一下「Terminal」分頁標籤,然後複製 vertex-ai-samples GitHub 存放區:

      git clone https://github.com/GoogleCloudPlatform/vertex-ai-samples.git
      

      指令執行完畢後,您會在 JupyterLab 環境的檔案瀏覽器窗格中看到 vertex-ai-samples 資料夾。

    6. 在檔案瀏覽器中,依序開啟 vertex-ai-samples>notebooks >community>exploratory_data_analysis。您會看到 eda_with_r_and_bigquery.ipynb 筆記本。

    開啟筆記本並設定 R

    1. 在檔案瀏覽器中,開啟 eda_with_r_and_bigquery.ipynb 筆記本。

      這個筆記本將逐步說明如何使用 R 和 BigQuery 進行探索性資料分析。在本文件的其餘部分,您會在筆記本中作業,並執行 Jupyter 筆記本中顯示的程式碼。

    2. 查看筆記本使用的 R 版本:

      version
      

      輸出內容中的 version.string 欄位應顯示 R version 4.3.2,這是您在上一個章節中安裝的項目。

    3. 檢查並安裝必要的 R 封裝函式 (如果目前工作階段中尚未提供):

      # List the necessary packages
      needed_packages <- c("dplyr", "ggplot2", "bigrquery")
      
      # Check if packages are installed
      installed_packages <- .packages(all.available = TRUE)
      missing_packages <- needed_packages[!(needed_packages %in% installed_packages)]
      
      # If any packages are missing, install them
      if (length(missing_packages) > 0) {
        install.packages(missing_packages)
      }
      
    4. 載入必要套件:

      # Load the required packages
      lapply(needed_packages, library, character.only = TRUE)
      
    5. 使用頻外驗證方式驗證 bigrquery

      bq_auth(use_oob = True)
      
    6. [YOUR-PROJECT-ID] 替換為名稱,設定要用於這個筆記本的專案名稱:

      # Set the project ID
      PROJECT_ID <- "[YOUR-PROJECT-ID]"
      
    7. [YOUR-BUCKET-NAME] 替換為全域不重複的名稱,設定要儲存輸出資料的 Cloud Storage bucket 名稱:

      BUCKET_NAME <- "[YOUR-BUCKET-NAME]"
      
    8. 設定稍後在筆記本中產生的繪圖預設高度和寬度:

      options(repr.plot.height = 9, repr.plot.width = 16)
      

    查詢 BigQuery 資料

    在本節的筆記本中,您會將執行 BigQuery SQL 陳述式的結果讀取到 R 中,並初步查看資料。

    1. 建立 BigQuery SQL 陳述式,從行程樣本中擷取一些可能的預測因子和目標預測變數。下列查詢會篩除要讀取以進行分析的欄位中,部分離群值或無意義的值。

      sql_query_template <- "
          SELECT
            TIMESTAMP_DIFF(dropoff_datetime, pickup_datetime, MINUTE) AS trip_time_minutes,
      
            passenger_count,
      
            ROUND(trip_distance, 1) AS trip_distance_miles,
      
            rate_code,
            /* Mapping from rate code to type from description column in BigQuery table schema */
            (CASE
              WHEN rate_code = '1.0'
                THEN 'Standard rate'
              WHEN rate_code = '2.0'
                THEN 'JFK'
              WHEN rate_code = '3.0'
                THEN 'Newark'
              WHEN rate_code = '4.0'
                THEN 'Nassau or Westchester'
              WHEN rate_code = '5.0'
                THEN 'Negotiated fare'
              WHEN rate_code = '6.0'
                THEN 'Group ride'
              /* Several NULL AND some '99.0' values go here */
              ELSE 'Unknown'
              END)
              AS rate_type,
      
            fare_amount,
      
            CAST(ABS(FARM_FINGERPRINT(
              CONCAT(
                CAST(trip_distance AS STRING),
                CAST(fare_amount AS STRING)
                )
              ))
              AS STRING)
              AS key
      
          FROM
            `bigquery-public-data.new_york_taxi_trips.tlc_yellow_trips_2022`
      
          /* Filter out some outlier or hard to understand values */
          WHERE
            (TIMESTAMP_DIFF(dropoff_datetime, pickup_datetime, MINUTE)
              BETWEEN 0.01 AND 120)
            AND
            (passenger_count BETWEEN 1 AND 10)
            AND
            (trip_distance BETWEEN 0.01 AND 100)
            AND
            (fare_amount BETWEEN 0.01 AND 250)
      
          LIMIT %s
      "
      

      key 資料欄是根據 trip_distancefare_amount 資料欄的串連值產生的資料列 ID。

    2. 執行查詢並擷取與記憶體內資料表相同的資料,這類似於資料框架。

      sample_size <- 10000
      
      sql_query <- sprintf(sql_query_template, sample_size)
      
      taxi_trip_data <- bq_table_download(
          bq_project_query(
              PROJECT_ID,
              query = sql_query
          )
      )
      
    3. 查看擷取的結果:

      head(taxi_trip_data)
      

      輸出內容會是類似下圖的表格:

      計程車行程資料的前六列。

      結果會顯示以下行程資料欄:

      • trip_time_minutes 整數
      • passenger_count 整數
      • trip_distance_miles二壘安打
      • rate_code 個字元
      • rate_type 個字元
      • fare_amount二壘安打
      • key 個字元
    4. 查看各欄的列數和資料類型:

      str(taxi_trip_data)
      

      輸出結果會與下列內容相似:

      tibble [10,000 x 7] (S3: tbl_df/tbl/data.frame)
      $ trip_time_minutes  : int [1:10000] 52 19 2 7 14 16 1 2 2 6 ...
      $ passenger_count    : int [1:10000] 1 1 1 1 1 1 1 1 3 1 ...
      $ trip_distance_miles: num [1:10000] 31.3 8.9 0.4 0.9 2 0.6 1.7 0.4 0.5 0.2 ...
      $ rate_code          : chr [1:10000] "5.0" "5.0" "5.0" "5.0" ...
      $ rate_type          : chr [1:10000] "Negotiated fare" "Negotiated fare" "Negotiated fare" "Negotiated fare" ...
      $ fare_amount        : num [1:10000] 0.01 0.01 0.01 0.01 0.01 0.01 0.01 0.01 0.01 0.01 ...
      $ key                : chr [1:10000] "1221969315200336084" 5007772749405424948" "3727452358632142755" "77714841168471205370" ...
      
    5. 查看擷取資料的摘要:

      summary(taxi_trip_data)
      

      輸出結果會與下列內容相似:

      trip_time_minutes passenger_count trip_distance_miles  rate_code
      Min.   :  1.00    Min.   :1.000   Min.   : 0.000      Length:10000
      1st Qu.: 20.00    1st Qu.:1.000   1st Qu.: 3.700      Class :character
      Median : 24.00    Median :1.000   Median : 4.800      Mode  :character
      Mean   : 30.32    Mean   :1.465   Mean   : 9.639
      3rd Qu.: 39.00    3rd Qu.:2.000   3rd Qu.:17.600
      Max.   :120.00    Max.   :9.000   Max.   :43.700
      rate_type          fare_amount         key
      Length:10000       Min.   :  0.01   Length:10000
      Class :character   1st Qu.: 16.50   Class :character
      Mode  :character   Median : 16.50   Mode  :character
                        Mean   : 31.22
                        3rd Qu.: 52.00
                        Max.   :182.50
      

    使用 ggplot2 製作資料圖表

    在本節的筆記本中,您將使用 R 中的 ggplot2 程式庫,研究範例資料集中的部分變數。

    1. 使用直方圖顯示 fare_amount 值的分布情形:

      ggplot(
          data = taxi_trip_data,
          aes(x = fare_amount)
          ) +
      geom_histogram(bins = 100)
      

      產生的圖表類似下圖:

      這張圖表顯示車資金額的分布情形,車資金額值為 20 和 52 時會出現尖峰。

    2. 使用散布圖顯示「trip_distance」和「fare_amount」之間的關聯:

      ggplot(
          data = taxi_trip_data,
          aes(x = trip_distance_miles, y = fare_amount)
          ) +
      geom_point() +
      geom_smooth(method = "lm")
      

      產生的圖表類似下圖:

      顯示行程距離與車資金額關係的散布圖,並附上線性迴歸平滑線。

    從 R 處理 BigQuery 中的資料

    處理大型資料集時,建議您盡可能在 BigQuery 中執行分析 (包括彙整、篩選、聯結、計算資料欄等),然後擷取結果。在 R 中執行這些工作效率較低。使用 BigQuery 進行分析時,可充分運用 BigQuery 的擴充性和效能,並確保傳回的結果可放入 R 的記憶體中。

    1. 在筆記本中,建立函式來找出所選資料欄中每個值的行程數和平均車資金額:

      get_distinct_value_aggregates <- function(column) {
          query <- paste0(
              'SELECT ',
                column,
                ',
                COUNT(1) AS num_trips,
                AVG(fare_amount) AS avg_fare_amount
      
              FROM
                `bigquery-public-data.new_york_taxi_trips.tlc_yellow_trips_2022`
      
              WHERE
                (TIMESTAMP_DIFF(dropoff_datetime, pickup_datetime, MINUTE)
                  BETWEEN 0.01 AND 120)
                AND
                (passenger_count BETWEEN 1 AND 10)
                AND
                (trip_distance BETWEEN 0.01 AND 100)
                AND
                (fare_amount BETWEEN 0.01 AND 250)
      
              GROUP BY 1
              '
              )
      
          bq_table_download(
              bq_project_query(
                  PROJECT_ID,
                  query = query
              )
          )
      }
      
    2. 使用 trip_time_minutes 欄位叫用函式,該欄位是使用 BigQuery 中的時間戳記功能定義:

      df <- get_distinct_value_aggregates(
        'TIMESTAMP_DIFF(dropoff_datetime, pickup_datetime, MINUTE) AS trip_time_minutes')
      
      ggplot(
          data = df,
          aes(x = trip_time_minutes, y = num_trips)
          ) +
      geom_line()
      
      ggplot(
          data = df,
          aes(x = trip_time_minutes, y = avg_fare_amount)
          ) +
      geom_line()
      

      筆記本會顯示兩張圖表。第一個圖表會顯示各趟行程的長度 (以分鐘為單位)。第二張圖表顯示行程的平均車資金額 (依行程時間計算)。

      第一個 ggplot 指令的輸出內容如下,顯示按行程長度 (以分鐘為單位) 分類的行程數量:

      曲線顯示,行程時間在 0 到 10 分鐘時,行程次數最高,但隨著行程時間接近 25 分鐘,次數會大幅下降。

      第二個 ggplot 指令的輸出內容如下所示,顯示依行程時間計算的平均車資金額:

      曲線顯示從 0 分鐘到 50 分鐘,平均車資金額穩定增加,從 50 分鐘到 125 分鐘,則以較慢的速度增加。

      如要查看更多使用資料中其他欄位的視覺化範例,請參閱筆記本。

    將資料儲存為 Cloud Storage 中的 CSV 檔案

    下一個工作是將從 BigQuery 擷取的資料儲存為 Cloud Storage 中的 CSV 檔案,以便用於後續的機器學習工作。

    1. 在筆記本中,將 BigQuery 中的訓練和評估資料載入 R:

      # Prepare training and evaluation data from BigQuery
      sample_size <- 10000
      
      sql_query <- sprintf(sql_query_template, sample_size)
      
      # Split data into 75% training, 25% evaluation
      train_query <- paste('SELECT * FROM (', sql_query,
        ') WHERE MOD(CAST(key AS INT64), 100) <= 75')
      eval_query <- paste('SELECT * FROM (', sql_query,
        ') WHERE MOD(CAST(key AS INT64), 100) > 75')
      
      # Load training data to data frame
      train_data <- bq_table_download(
          bq_project_query(
              PROJECT_ID,
              query = train_query
          )
      )
      
      # Load evaluation data to data frame
      eval_data <- bq_table_download(
          bq_project_query(
              PROJECT_ID,
              query = eval_query
          )
      )
      
    2. 檢查每個資料集中的觀測值數量:

      print(paste0("Training instances count: ", nrow(train_data)))
      
      print(paste0("Evaluation instances count: ", nrow(eval_data)))
      

      大約 75% 的執行個體總數應用於訓練,其餘執行個體則大約有 25% 用於評估。

    3. 將資料寫入本機 CSV 檔案:

      # Write data frames to local CSV files, with headers
      dir.create(file.path('data'), showWarnings = FALSE)
      
      write.table(train_data, "data/train_data.csv",
        row.names = FALSE, col.names = TRUE, sep = ",")
      
      write.table(eval_data, "data/eval_data.csv",
        row.names = FALSE, col.names = TRUE, sep = ",")
      
    4. 將 CSV 檔案上傳至 Cloud Storage,方法是包裝傳遞至系統的 gsutil 指令:

      # Upload CSV data to Cloud Storage by passing gsutil commands to system
      gcs_url <- paste0("gs://", BUCKET_NAME, "/")
      
      command <- paste("gsutil mb", gcs_url)
      
      system(command)
      
      gcs_data_dir <- paste0("gs://", BUCKET_NAME, "/data")
      
      command <- paste("gsutil cp data/*_data.csv", gcs_data_dir)
      
      system(command)
      
      command <- paste("gsutil ls -l", gcs_data_dir)
      
      system(command, intern = TRUE)
      

      您也可以使用 googleCloudStorageR 程式庫將 CSV 檔案上傳至 Cloud Storage,該程式庫會叫用 Cloud Storage JSON API

    您也可以使用 bigrquery,將資料從 R 寫回 BigQuery。通常在完成一些前置處理或產生結果後,會將資料寫回 BigQuery,以供進一步分析。

    清除所用資源

    如要避免系統向您的 Google Cloud 帳戶收取本文所用資源的費用,請將資源全數移除。

    刪除專案

    如要避免付費,最簡單的方法就是刪除您建立的專案。如果打算探索多種架構、教學課程或快速入門導覽課程,重複使用專案有助於避免超出專案配額限制。

    1. In the Google Cloud console, go to the Manage resources page.

      Go to Manage resources

    2. In the project list, select the project that you want to delete, and then click Delete.
    3. In the dialog, type the project ID, and then click Shut down to delete the project.

    後續步驟

    • 如要進一步瞭解如何在 R 筆記本中使用 BigQuery 資料,請參閱 bigrquery 說明文件
    • 參閱機器學習的規則,瞭解機器學習工程的最佳做法。
    • 如要瞭解適用於 Google Cloud 中 AI 和機器學習工作負載的架構原則和建議,請參閱 Well-Architected Framework 中的「 Google CloudAI 和機器學習觀點」。
    • 如需更多參考架構、圖表和最佳做法,請瀏覽 Cloud 架構中心

    貢獻者

    作者:Alok Pattani | 開發人員服務代表

    其他貢獻者: