Pandas 是 Python 資料科學領域中不可或缺的工具,它提供高效的資料結構和資料處理功能。在實際應用中,選擇合適的資料儲存格式和序列化方法至關重要。Apache Parquet 作為一種高效的儲存格式,能有效提升資料讀寫效能,並保留資料型別資訊。Pandas 也提供完整的 JSON 處理機制,讓使用者能靈活地將資料轉換為 JSON 格式,或從 JSON 資料中讀取資料。此外,Pandas 還支援從網頁中擷取表格資料,方便使用者快速取得網路上的公開資料。這些功能的結合,讓 Pandas 成為資料處理的利器,提升資料分析和處理的效率。

參考資源

對於想要深入瞭解ADBC的讀者,建議觀看相關的技術演講和檔案:

  • PyData NYC 2023演講:Faster SQL with pandas and Apache Arrow
  • ADBC官方檔案:ADBC Driver Implementation Status

這些資源將有助於更深入地理解ADBC的技術細節和實際應用場景。

Apache Parquet:高效的資料儲存格式

在眾多資料儲存格式中,Apache Parquet 是儲存 pandas DataFrame 的最佳選擇。Apache Parquet 提供了多項優勢,包括:

  • 中繼資料儲存:能夠追蹤資料型別等特性
  • 分割儲存:資料不需要全部儲存在單一檔案中
  • 查詢支援:可以直接在磁碟上查詢 Parquet 檔案,無需將所有資料載入記憶體
  • 平行處理:支援平行讀取資料以提高處理效率
  • 精簡儲存:資料經過壓縮,以高效的方式儲存

除非需要與舊系統相容,否則在大多數工作流程中,Apache Parquet 格式應該取代 CSV 檔案的使用,從本地資料持久化儲存到與團隊成員分享資料,乃至跨系統交換資料。

如何使用 Apache Parquet

讀取和寫入 Apache Parquet 的 API 與其他 pandas API 一致:使用 pd.read_parquet 讀取,而 pd.DataFrame.to_parquet 方法用於寫入。

首先,建立一些範例資料並使用 io.BytesIO 物件:

import io
import pandas as pd

buf = io.BytesIO()
df = pd.DataFrame([
    ["Paul", "McCartney", 1942],
    ["John", "Lennon", 1940],
    ["Richard", "Starkey", 1940],
    ["George", "Harrison", 1943],
], columns=["first", "last", "birth"])

# 將 DataFrame 寫入 buf
df.to_parquet(buf, index=False)

# 從 buf 讀取資料
buf.seek(0)
read_df = pd.read_parquet(buf)
print(read_df)

內容解密:

此範例展示瞭如何使用 io.BytesIO 物件作為緩衝區,將 pandas DataFrame 寫入並讀取為 Apache Parquet 格式。to_parquet 方法用於將 DataFrame 寫入緩衝區,而 read_parquet 函式則用於從緩衝區讀取資料。由於 Apache Parquet 格式儲存了資料的中繼資料,因此在讀取資料時無需指定資料型別。

資料型別保留

Apache Parquet 格式能夠保留原始資料的型別。讓我們來驗證這一點:

# 修改 birth 列的資料型別
df["birth"] = df["birth"].astype(pd.UInt16Dtype())

# 將 DataFrame 寫入並讀取
buf = io.BytesIO()
df.to_parquet(buf, index=False)
buf.seek(0)
read_df = pd.read_parquet(buf)

# 檢查資料型別
print(read_df.dtypes)

內容解密:

此範例展示了 Apache Parquet 格式如何保留原始資料的型別。無論是寫入還是讀取,資料型別都能正確保留。

資料分割

Apache Parquet 支援資料分割,這使得資料不需要儲存在單一檔案中。以下是一個範例:

# 假設資料儲存在 data/partitions 目錄下
# 資料夾結構如下:
# data/partitions/2022/q1_sales.parquet
# data/partitions/2022/q2_sales.parquet
# data/partitions/2023/q1_sales.parquet
# data/partitions/2023/q2_sales.parquet

# 直接讀取整個目錄
df = pd.read_parquet("data/partitions/")
print(df)

內容解密:

此範例展示瞭如何使用 read_parquet 函式直接讀取整個目錄下的 Parquet 檔案。Apache Parquet 格式支援將資料儲存在多個檔案中,並能夠自動合併這些檔案。

資料過濾

在處理大型資料集時,可以使用 filters 引數對資料進行過濾:

# 只讀取 region 為 Europe 的資料
df_filtered = pd.read_parquet("data/partitions/", filters=[("region", "==", "Europe")])
print(df_filtered)

內容解密:

此範例展示瞭如何使用 filters 引數對資料進行過濾。透過指定篩選條件,可以減少需要載入記憶體的資料量。

JSON 資料格式

JavaScript 物件表示法(JSON)是一種常見的資料交換格式,用於在網路上傳輸資料。

  flowchart TD
 A[開始] --> B{檢查資料}
 B -->|資料有效| C[處理資料]
 B -->|資料無效| D[回報錯誤]
 C --> E[完成處理]
 D --> E

圖表翻譯:

此圖示展示了一個基本的資料處理流程。流程始於「開始」階段,接著進行資料有效性檢查。若資料有效,系統會進入「處理資料」階段;若資料無效,則轉向「回報錯誤」階段。最後,無論資料處理成功與否,流程都會到達「完成處理」階段。此圖清晰地說明瞭程式中的條件分支邏輯以及不同處理路徑的銜接方式,幫助讀者理解整體處理邏輯。

pandas 資料輸入/輸出系統中的 JSON 處理機制

pandas 函式庫提供了多種方法來處理 JSON 格式的資料,使得資料的序列化和反序列化變得更加靈活和高效。本文將深入探討 pandas 如何利用 pd.read_jsonpd.DataFrame.to_json 方法來讀寫 JSON 資料,以及不同的 orient 引數對資料儲存格式的影響。

使用 JSON 格式儲存和讀取 pandas 資料

Python 標準函式庫中的 json 模組可以用來序列化和反序列化 Python 物件。然而,當涉及到 pandas 物件時,pandas 提供了自己的 I/O 函式來處理 JSON 格式的資料。

基礎範例:JSON 資料的讀寫

首先,我們來看一個簡單的例子,展示如何使用 json 模組來處理 Python 字典物件:

import json

beatles = {
    "first": ["Paul", "John", "Richard", "George"],
    "last": ["McCartney", "Lennon", "Starkey", "Harrison"],
    "birth": [1942, 1940, 1940, 1943],
}

serialized = json.dumps(beatles)
print(f"序列化後的資料:{serialized}")

deserialized = json.loads(serialized)
print(f"反序列化後的資料:{deserialized}")

內容解密:

此範例展示瞭如何使用 json.dumps 將 Python 字典序列化為 JSON 字串,以及如何使用 json.loads 將 JSON 字串反序列化回 Python 字典。這個過程對於資料儲存和交換非常有用。

pandas 中的 JSON 處理

pandas 提供了 pd.read_jsonpd.DataFrame.to_json 方法來處理 JSON 格式的資料。下面是一個簡單的例子:

import io
import pandas as pd

data = io.StringIO(serialized)
df = pd.read_json(data, dtype_backend="numpy_nullable")
print(df)

輸出結果:

   first      last  birth
0    Paul  McCartney   1942
1    John      Lennon   1940
2  Richard     Starkey   1940
3   George    Harrison   1943

內容解密:

這段程式碼展示瞭如何使用 pd.read_json 從 JSON 資料中讀取資料並建立 DataFrame 物件。dtype_backend="numpy_nullable" 引數確保了資料型別的正確處理。

使用 orient 引數控制 JSON 資料的格式

pd.DataFrame.to_json 方法允許透過 orient 引數來控制輸出的 JSON 資料的格式。不同的 orient 值會影響資料的儲存方式和可讀性。

orient="columns"(預設值)

df = pd.DataFrame(beatles, index=["row0", "row1", "row2", "row3"])
serialized = df.to_json(orient="columns")
print(f'Length of orient="columns": {len(serialized)}')
print(serialized[:100])

輸出結果:

Length of orient="columns": 221
{"first":{"row0":"Paul","row1":"John","row2":"Richard","row3":"George"},"last":{"row0":"McCartney","row1":"Lennon","row2":"Starkey","row3":"Harrison"},"birth":{"row0":1942,"row1":1940,"row2":1940,"row3":1943}}

內容解密:

當使用 orient="columns" 時,JSON 資料以欄位為單位進行組織,每個欄位對應一個字典,鍵是列索引,值是資料點。這種格式在重建 DataFrame 時表現良好,但可能會重複儲存列索引。

不同 orient 引數的比較

orient 描述 長度 重建 DataFrame 能力
columns 以欄位為單位儲存資料 較長 良好
records 每列資料儲存為一個字典 中等 丟失列索引
split 將欄位、索引和資料分開儲存 較短 良好
index 以列索引為單位儲存資料 較長 良好
values 只儲存資料值 最短 丟失所有索引資訊
table 遵循 JSON Table Schema 最長 最完整
  flowchart TD
    A[開始] --> B{選擇 orient 引數}
    B -->|columns| C[以欄位為單位儲存]
    B -->|records| D[每列資料儲存為字典]
    B -->|split| E[分開儲存欄位、索引和資料]
    B -->|index| F[以列索引為單位儲存]
    B -->|values| G[只儲存資料值]
    B -->|table| H[遵循 JSON Table Schema]
    C --> I[結束]
    D --> I
    E --> I
    F --> I
    G --> I
    H --> I

圖表翻譯:

此圖示展示了在選擇不同的 orient 引數時,JSON 資料的儲存格式會如何變化。從「開始」節點出發,根據選擇的 orient 值,會進入不同的儲存格式分支,最終都到達「結束」節點。這個流程圖清晰地說明瞭不同 orient 引數對 JSON 資料格式的影響。

pandas I/O系統詳解:資料序列化與反序列化技術

pandas 函式庫提供了強大的 I/O 功能,讓使用者能夠輕鬆地將 DataFrame 物件序列化為不同的資料格式,並在需要時重新讀取。這些功能對於資料儲存、傳輸和交換至關重要。本篇文章將深入探討 pandas 中的 JSON 序列化技術,並介紹如何使用 pd.read_html 從網頁中擷取表格資料。

JSON序列化技術

在 pandas 中,DataFrame 物件可以透過 to_json 方法序列化為 JSON 格式。這個方法提供了多種不同的序列化選項,讓使用者可以根據需求選擇最合適的輸出格式。

不同序列化格式的比較

pandas 支援多種 JSON 序列化格式,主要透過 orient 引數進行控制。以下是幾種常見的格式:

  1. columns 定向(預設):將 DataFrame 以欄位為單位進行序列化。
import pandas as pd

# 建立範例 DataFrame
data = {
    'first': ['Paul', 'John', 'Richard', 'George'],
    'last': ['McCartney', 'Lennon', 'Starkey', 'Harrison'],
    'birth': [1942, 1940, 1940, 1943]
}
df = pd.DataFrame(data)

# 序列化為 JSON(columns 定向)
serialized = df.to_json(orient='columns')
print(serialized)
  1. index 定向:以索引為主的序列化方式。
# 序列化為 JSON(index 定向)
serialized_index = df.to_json(orient='index')
print(serialized_index)
  1. values 定向:僅儲存資料值,不包含欄位名稱和索引。
# 序列化為 JSON(values 定向)
serialized_values = df.to_json(orient='values')
print(serialized_values)
  1. table 定向:使用 JSON Table Schema 格式儲存資料及中繼資料。
# 序列化為 JSON(table 定向)
serialized_table = df.to_json(orient='table')
print(serialized_table)

不同格式的特性比較

格式 描述 長度 特性
columns 以欄位為單位序列化 中等 保留欄位名稱
index 以索引為主的序列化 較長 保留索引資訊
values 僅儲存資料值 最短 不保留欄位名稱和索引
table 使用 JSON Table Schema 最長 保留資料型別等中繼資料

使用 pd.json_normalize 處理複雜 JSON 資料

當遇到複雜的 JSON 資料結構時,pd.json_normalize 函式可以將巢狀結構的資料扁平化為表格形式。

基本用法

import pandas as pd

# 建立範例 JSON 資料
data = {
    "records": [
        {"name": "human", "characteristics": {"num_leg": 2, "num_eyes": 2}},
        {"name": "dog", "characteristics": {"num_leg": 4, "num_eyes": 2}},
        {"name": "horseshoe crab", "characteristics": {"num_leg": 10, "num_eyes": 10}}
    ],
    "type": "animal",
    "pagination": {
        "next": "23978sdlkusdf97234u2io",
        "has_more": 1
    }
}

# 使用 pd.json_normalize 處理資料
df_normalized = pd.json_normalize(data, record_path='records')
print(df_normalized)

保留額外中繼資料

# 同時保留 "type" 資訊
df_normalized_with_meta = pd.json_normalize(data, record_path='records', meta='type')
print(df_normalized_with_meta)

從網頁中擷取表格資料

pandas 提供了 read_html 函式,可以直接從網頁中擷取表格資料。以下以擷取維基百科上的披頭士樂隊唱片目錄為例,說明如何使用這個功能。

實作步驟

  1. 安裝必要的函式庫
python -m pip install lxml
  1. 擷取網頁中的表格
import pandas as pd

# 目標網址
url = 'https://en.wikipedia.org/wiki/The_Beatles_discography'

# 擷取表格資料
dfs = pd.read_html(url)

# 檢視擷取到的表格數量
print(f'共擷取到 {len(dfs)} 個表格')
  1. 選擇正確的表格
# 檢視第一個表格的內容
print(dfs[0].head())

# 使用 attrs 引數精確定位需要的表格
# dfs = pd.read_html(url, attrs={'class': 'wikitable'})

處理複雜的 HTML 結構

當網頁中的表格沒有明確的 id 屬性時,可以使用其他屬性(如 class)來定位:

# 使用 attrs 引數
tables = pd.read_html(url, attrs={'class': 'wikitable plainrowheaders'})

最佳實踐與注意事項

  1. 選擇適當的序列化格式

    • 根據使用場景選擇合適的 orient 引數。
    • 考慮資料的完整性和可讀性。
  2. 處理複雜 JSON 資料

    • 使用 pd.json_normalize 處理巢狀結構。
    • 適當使用 record_pathmeta 引數。
  3. 網頁資料擷取

    • 確認目標網站是否允許網頁抓取。
    • 使用適當的 attrs 引數定位需要的表格。
  4. 效能最佳化

    • 對於大型資料集,考慮使用更高效的資料格式(如 Parquet)。
    • 適當使用資料型別轉換(如 convert_dtypes)。
圖表翻譯:

此流程圖展示了使用 pandas 處理不同資料來源的一般流程。首先,根據資料來源選擇適當的處理方法:對於 JSON 資料,使用 pd.json_normalize 進行處理;對於網頁表格,則使用 pd.read_html 擷取資料。接著,根據資料特性選擇適當的序列化格式或進行進一步的資料處理。最終完成資料處理流程。這個流程圖清晰地說明瞭 pandas 在處理不同資料來源時的應用邏輯。