---
# System prepended metadata

title: 2_pandas–資料處理套件介紹
tags: [機器學習教材]

---

# W3教材大綱: pandas–資料處理套件介紹
## Source
- 成為python數據分析達人的第一堂課 5
- [website](https://blog.techbridge.cc/2020/09/21/python-pandas-zen-tutorial/)
- 大數據分析與資料探勘 
    - W2 P29-41
    - W3
- 練習資料集: grades.csv
- [Website: Pandas資料合併技巧](https://medium.com/@hui509/pandas-%E8%B3%87%E6%96%99%E5%90%88%E4%BD%B5%E7%9A%84%E4%B8%89%E7%A8%AE%E5%B8%B8%E7%94%A8%E8%AA%9E%E6%B3%95-cd2918774efe)
- [Website圖片](https://hackmd.io/@linweipo/r1lkaXGlK)

## 淳瑜的Gamma prompt
- Write for: 剛開始接觸機器學習，正在學習資料分析和 Pandas，且有一些python基礎的初學者
- Tone: 專業、有邏輯、教導、重點明確
- Additional instructions: 請生成大學機器學習教學投影片，教授對象是僅有微弱python基礎的文商學院同學，請盡可能展示所有程式碼及教學細節

## 課堂投影片與練習
- [x] **資料處理的重要性**
- 資料品質和資料完整性決定資料探勘效果的好壞。
- 資料蒐集的方式(或工具)各異,導致資料庫或資料倉儲可能存在著許多資料雜訊、資料遺漏及資料格式不一致的狀況;加上大數據資料具有4V特性,若直接分析原始資料,很可能因資料品質不佳而導致事倍功半的結果或有偏誤的結論。
- 資料準備(data preparation)是指在瞭解問題與目的之後,進行資料探勘與建立模式之前,為確保分析資料品質和分析結果正確性所進行的資料蒐集、資料預處理、資料轉換及資料分割等一連串程序。
---

- [x] **為什麼要學 Pandas？**

    *   可以簡單地將 Pandas 想成是 **Python 裡面的 Excel**。
    *   為什麼重要？在數據分析中，我們常說 **80% 的時間都花在「資料清理」**上。Pandas 就是幫助我們完成這項任務的強大工具。
    *   Pandas 是 Python 之所以能在數據分析領域佔據龍頭地位的重要原因之一。
    *   學習 Pandas 能讓你更方便地使用程式來整理資料，比手動操作 Excel 更有效率、更不容易出錯。
    *   掌握 Pandas 是邁向數據分析和機器學習的第一步！

---

- [x] **開始使用 Pandas**

    *   就像使用 NumPy 和 Matplotlib 一樣，使用 Pandas 前需要先匯入。
    *   標準的匯入方式是：`import pandas as pd`。
    *   每次進行數據分析或機器學習前，建議在 Jupyter Notebook 中先執行以下標準指令：
        ```python=
        %matplotlib inline
        import numpy as np
        import matplotlib.pyplot as plt
        import pandas as pd
        ```
---
- [x] **課堂練習: 安裝 Pandas 並在 Python 環境中導入**
    1. 指導學生在命令行中輸入：
       ```
       pip install pandas
       ```
    2. 在 Python 環境中導入 Pandas：
       ```python
       import pandas as pd
       ```
    3. 確認安裝成功：
       ```python
       print(pd.__version__)
       ```


---

- [x] **Pandas 的核心資料結構**

    *   Pandas 主要有兩種核心的資料結構：
        1.  **Series (序列)**
            *   可以想成是一個有「名字」（index）的 List 或 NumPy Array。
            *   通常是 DataFrame 中的**單一欄位**。
            *   例如，一串學生的「國文」成績，就可以是一個 Series。
        2.  **DataFrame (資料框)**
            *   可以想成就是一張**表格**，就像 Excel 的試算表。
            *   這是 Pandas 中最標準、最常用的資料結構。
            *   包含「列」（Row）和「行」（Column）。
            *   每一列的前面有「index」（索引），每一行的上面有「columns」（欄位名）。

---
- [x] **課堂練習: 建立 Series**
1. 創建帶有自定義索引的 Series：
   ```python
   grades = pd.Series([60, 27, 72, 53], index=['小郭', '小王', '小華', '小明'])
   print(grades)
   ```

2. 使用索引取值：
   ```python
   print(grades['小王'])
   print(grades[1:3])
   ```
---
- [x] **課堂練習: 建立 DataFrame**

1. 準備傳入 Dataframe 的資料：
   ```python
   data = {
       'name': ['多拉A夢', '大雄', '小夫', '胖虎'],
       'email': ['Dora@gmail.com', 'hibino@gmail.com', 'rich@gmail.com', 'goodSinger@gmail.com'],
       'grades': [60, 77, 92, 43]
   }
   df = pd.DataFrame(data)
   print(df)
   ```

2. 建立 DataFrame：
   ```python
   df_custom = pd.DataFrame(data, index=['one', 'second', 'third', 'fourth'])
   print(df_custom)
   ```
---

- [x] **DataFrame 與 NumPy 的關係**

    *   雖然 Pandas 提供了很多數據分析功能，但有時我們仍需要將 Pandas 的 Series 或 DataFrame 轉換成 NumPy Array。
    *   這是因為某些複雜的數值運算或特定的函式庫需要 NumPy Array 作為輸入。
    *   **如何轉換？** 在 Series 或 DataFrame 後面加上 `.values` 屬性。
    *   範例：`df['國文'].values` 會將「國文」這個 Series 轉換成 NumPy Array。
    *   你可以使用 `type()` 函式來檢查資料的類型。

---
- [x] **使用 Pandas - 讀取資料**

    *   Pandas 可以讀取幾乎所有常見的資料格式，特別是 **CSV** 和 Excel 檔案。
    *   **讀取 CSV 檔案：** 使用 `pd.read_csv()` 函式。
        *   可以讀取本地的檔案：`df = pd.read_csv('檔案名稱.csv')`.
        *   也可以直接讀取網路上的檔案 (只要網址指向一個 CSV 檔案)：`df = pd.read_csv('http://檔案網址/檔案名稱.csv')`。
    *   我們習慣將讀入的 DataFrame 存到一個變數，通常簡稱 `df`。

---

- [x] **課堂練習：基礎操作與資料載入**

1.  下載課程提供的 csv檔案==(須提供資料集)==
2.  讀取 CSV 文件
    ```python
    df= pd.read_csv('grades.csv')
    print(df.head())
    ```
3. 將 DataFrame 寫入 CSV 文件：
   ```python
   df.to_csv('grades2.csv', index=False)
   ```
---
- [x] **初步探索資料**

    *   讀入資料後，第一件要做的事通常是**查看資料的樣子**，確認讀入是否正確。
    *   使用 `.head()` 方法：`df.head()`。
        *   會顯示 DataFrame 的**前 5 筆**資料（預設值）。
        *   可以指定顯示筆數：`df.head(10)` 會顯示前 10 筆。
    *   DataFrame 包含：
        *   **Index:** 每一列前面的標籤或名字 (預設從 0 開始的數字)。
        *   **Columns:** 每一行上面的欄位名稱。
        *   df.index(), df.columns
    * 列出 DataFrame 資訊

---

- [x] **課堂練習: DataFrame 基本操作**
1. 列出 DataFrame 資訊：
   ```python
   print(df.info())
   ```

2. 查看 DataFrame 的頭尾部分：
   ```python
   print(df.head(3))
   print(df.tail(3))
   ```

3. 查看索引和列名：
   ```python
   print(df.index)
   print(df.columns)
    ```
---
- [x] **欄位存取**

*   **如何存取單一欄位 (Column)？**
    *   使用中括號 `[]`：`df['姓名']`。這是最常用且彈性的方法。
    *   使用點記法 `.`: `df.姓名`。方便但不適用於所有情況 (例如欄位名有空格或特殊字元、中文)。
    *   存取結果會是一個 **Series**。
```python=
# 存取「姓名」欄位
print(df['姓名'])
```
- 若要取得2個以上欄位資料,則需使用串列
```python=
df[['姓名', '性別']]
```
- 根據條件篩選資料
    - 範例: 找出英文成績超過 90 分的學生
```python=
df[df['英文'] > 90]    #可以print觀察結果喔!
```
---
- [x] **Pandas 的基本數據分析功能**

    *   Pandas 本身就提供了方便的基礎統計和分析功能。
    *   **單一欄位的統計：**
        *   計算平均值：`df['國文'].mean()` (來源未直接提供，但 `.std()` 等有提供，可推斷)。
        *   計算標準差：`df['國文'].std()`。
        *   計算最小值：`df['國文'].min()` (來源未直接提供，但 `.describe()` 有)。

---
- [x] **Pandas 的基本數據分析功能**
    *   **快速總覽數值欄位統計：** 使用 `.describe()` 方法。
        *   會一次計算出數值型欄位的：筆數 (count)、平均值 (mean)、標準差 (std)、最小值 (min)、25%/50%/75% 四分位數 (quantile)、最大值 (max)。
    *   **計算欄位間的相關性：** 使用 `.corr()` 方法。
        *   DataFrame 的 `.corr()` 會計算所有數值欄位之間的相關係數矩陣。
        *   可以計算兩個指定欄位之間的相關係數：`df['欄位1'].corr(df['欄位2'])`。
- 課堂練習
```python=
# 國文與數學成績的相關係數
df['國文'].corr(df['數學'])
```

---

- [x] **認識軸(axis)與軸操作**
    *   **重要的觀念：Axis (軸)**
        *   Pandas 很多操作（如求和、計算平均）需要指定方向 (軸)。
        *   `axis=0`: 表示沿著**列**的方向操作 (即對**每一行**做運算)。想像成是「垂直」或「往下」的方向。
        *   `axis=1`: 表示沿著**行**的方向操作 (即對**每一列**做運算)。想像成是「水平」或「往右」的方向。
        *   這點新手容易混淆，請多加練習
---
- [x] **數學運算結合新增欄位之應用**
*   **欄位間的數學運算：** Pandas DataFrame/Series 支援基本的數學運算符號 (`+`, `-`, `*`, `/`)。
*   計算總分，需要將**每一列**的科目成績加總。
    *   先取出需要加總的欄位：`df[['國文', '英文', '數學', '自然', '社會']]`。
    *   對這些欄位進行加總，方向是**跨欄位 (每一列)**，所以使用 `axis=1`。
```python=
# 計算總分（五科相加）
df['總積分'] = df[['國文', '英文', '數學', '自然', '社會']].sum(axis=1)

# 顯示前幾列確認
print(df.head())
```
*   計算加權成績 = 數學*1.5 + 英文。
```python=
df['主科'] = df['數學'] * 1.5 + df['英文']
```
- 課堂練習: 新增"平均分數"欄位
```python=
df['平均分'] = df['總分'] / 5
```
---
- [x] **新增欄位**

    *   我們可以很容易地在現有的 DataFrame 中新增欄位。
    *   新增欄位的方式是直接為一個新的欄位名稱賦值：`df['新欄位名稱'] = 值或計算結果`。
    *   新的欄位值可以是一個固定的值，也可以是對現有欄位進行運算得到的結果。

---

# 以下第二堂課

- [x] **資料操作 - 排序 (`sort_values`)**

    *   對資料進行排序是常見的需求，例如找出總積分最高的同學。
    *   使用 `.sort_values()` 方法可以根據一個或多個欄位的值對 DataFrame 的**列**進行排序。
    *   **指定排序依據的欄位：** 使用 `by` 參數。
        *   單一欄位：`df.sort_values(by='總積分')`。
        *   多個欄位：`df.sort_values(by=['主科', '總積分'])`。排序時會先依第一個欄位排序，值相同再依第二個，以此類推。
    *   **指定排序方向：** 使用 `ascending` 參數。
        *   `ascending=True`：由小到大排序 (預設值).
        *   `ascending=False`：由大到小排序.
    *   範例：`df.sort_values(by='總積分', ascending=False)` 會依總積分由高到低排序.
    *   排序操作預設會回傳一個新的 DataFrame，不會修改原始 DataFrame。

---

- [x] **資料操作 - 分組 (`groupby`)**

    *   當你想要根據某個欄位的分類（例如不同縣市、不同組別）來計算統計值時，就可以使用分組功能。
    *   使用 `.groupby()` 方法：`df.groupby('分類欄位名稱')`。
    *   `groupby()` 本身的回傳值是一個特殊的 GroupBy 物件，需要搭配**聚合 (Aggregation)** 函式才能得到結果。
    *   常見的聚合函式有：`.count()` (計算每組的數量)、`.mean()` (計算每組的平均值)、`.sum()` (計算每組的總和) 等。
    *   範例：統計每個州的 UFO 目擊次數。
        *   `df_state = df.groupby('State').count()`。
        *   這會根據 'State' 欄位分組，然後計算每個組（每個州）的行數（即目擊次數）。
    *   分組後的結果通常也是一個 DataFrame 或 Series，可以再進行排序、篩選等操作。

---

- [ ] **課堂練習：數據分析與操作**

    1.  **任務：** 使用您載入的 `df` DataFrame，計算所有數值欄位的基本統計資訊，並顯示出來。
    2.  **任務：** 計算「國文」和「數學」成績之間的相關係數。
    3.  **任務：** 為 DataFrame 新增一個名為「總分」的欄位，其值為所有科目成績的加總 (假設所有科目都是數值欄位)。**提示：** 注意使用正確的 `axis` 方向。
    4.  **任務：** 為 DataFrame 新增一個名為「平均分」的欄位，其值為總分除以科目數量 (假設有 5 個科目)。
    5.  **任務：** 根據「總分」欄位，將 DataFrame 由高到低排序，並顯示排序後的前 10 筆資料。

---
- [ ] Python 資料合併：Pandas 的強大工具
* 在數據分析中，資料合併是一個關鍵步驟
* Pandas 提供了多種合併方法，適用於不同場景
* 今天我們將學習三種主要的合併方法：
  1. concat()
  2. merge()
  3. join()

---

- [ ] Pandas 合併方法介紹與比較
* concat(): 用於簡單的垂直或水平合併
* merge(): 基於特定列或索引的智能合併
* join(): 基於索引的合併
* 選擇合適的方法取決於：
  - 資料結構
  - 合併需求
  - 效能考量
---

- [ ] **Concat**

    *   有時候你需要將不同的資料表合併起來，Pandas 提供了 `pd.concat()` 函式。
    *   `pd.concat()` 接受一個要合併的 DataFrame 列表 (List) 作為輸入。
    *   **指定合併方向：** 使用 `axis` 參數。
        *   `axis=0`：沿著**列**的方向合併 (上下疊)，這是預設值。就像在 Excel 中把一個表格貼到另一個表格的下方。
        *   `axis=1`：沿著**行**的方向合併 (左右接)，需要指定 `axis=1`。就像在 Excel 中把一個表格貼到另一個表格的右方。
    *   **水平合併 (`axis=1`) 的注意事項：** 如果合併的 DataFrame 列數不一致，缺少資料的地方會自動填入 `NaN` (Not a Number)，表示「遺失值」。
    *   合併後可能需要重設或修改索引 (Index)。
---
- [ ] merge()
* 用途：基於一個或多個鍵（列）合併 DataFrame
* 語法：`pd.merge(left, right, on=None, how='inner')`
* 參數：
  - left, right: 要合併的 DataFrame
  - on: 用於合併的列名
  - how: 合併方式（'inner', 'outer', 'left', 'right'）
* 適用場景：需要基於特定條件合併不同結構的資料集

---
- [ ] **Join**
    - Inner Join (取交集)，如 : pd.merge(df1,df2, left_on='cid', right_on='cid', how='inner')
    - Outer Join (取聯集)，如 : pd.merge(df1,df2, left_on='cid', right_on='cid', how='outer')
    - Left Join (以左邊DataFrame欄位為主體)，如 : pd.merge(df3,df4, left_on='cid', right_on='cid', how='left')
    - Right Join (以右邊DataFrame欄位為主體)，如 : pd.merge(df3,df4, left_on='cid', right_on='cid', how='right')
    
---

- [ ] **進階觀念：`.loc` 的使用**

    *   **新手最容易困惑的地方來了！** 當你想要「根據某些條件篩選資料，然後修改篩選出來的資料」時，常會遇到問題。
    *   例如，你想找到國文成績及格的同學，然後把他們的數學成績設定為 100。你可能會寫 `df[df['國文'] >= 60]['數學'] = 100`。
    *   但這樣做，**原始的 `df` 可能根本沒被修改！** 這是因為 `df[df['國文'] >= 60]` 可能會回傳一個新的 DataFrame 的**拷貝 (Copy)**，你修改的是這個拷貝，而不是原始資料。
    *   **解決方法：使用 `.loc`！** `.loc` 是 Pandas 中用於**基於標籤 (Label)** 進行選取和修改的強大工具。學會它會讓你覺得 Pandas 親切很多。
    *   `.loc` 的基本語法：`df.loc[row_indexer, column_indexer]`。
        *   `row_indexer` 可以是單個標籤、標籤列表、切片、布林值 Series (就是你的條件)。
        *   `column_indexer` 可以是單個欄位名、欄位名列表、切片。
    *   **正確的條件式修改範例：**
        *   選取國文成績大於等於 60 的**列**，以及「數學」這個**行**：`df.loc[df['國文'] >= 60, '數學']`
        *   將這些位置的值設定為 100：`df.loc[df['國文'] >= 60, '數學'] = 100`
    *   **總結：** 只要你想根據 index 或 column name 來**精確選取或修改** DataFrame 的特定位置，特別是進行條件式的修改，請**務必使用 `.loc`**！

---

- [ ] **課堂練習：使用 `.loc` 進行精確操作**

    1.  **任務：** 建立一個簡單的 DataFrame，包含至少兩列數值欄位（例如：'A' 和 'B'）和一些隨機數據。
        ```python=
        import pandas as pd
        import numpy as np
        df_test = pd.DataFrame(np.random.randn(5, 2), columns=['A', 'B'])
        print("原始 DataFrame:")
        print(df_test)
        ```
    2.  **任務：** 使用 `.loc` 選取 DataFrame 中 Index 為 1 和 3 的兩列資料，以及 'A' 欄位，並顯示出來。
        ```python=
        # 請在這裡寫你的程式碼
        ```
    3.  **任務：** 使用 `.loc` 選取 DataFrame 中 Index 為 2 的列，以及 'B' 欄位，並將其值修改為 999。然後再次顯示整個 DataFrame 檢查是否修改成功。
        ```python=
        # 請在這裡寫你的程式碼
        ```
    4.  **任務：** 使用 `.loc`，找出 DataFrame 中 'A' 欄位值大於 0 的列，將這些列的 'B' 欄位值全部設為 0。然後再次顯示整個 DataFrame 檢查是否修改成功。
        ```python=
        # 請在這裡寫你的程式碼
        ```
    5.  **討論：** 如果你在任務 4 中沒有使用 `.loc`，而是寫 `df_test[df_test['A'] > 0]['B'] = 0`，可能會發生什麼情況？為什麼 `.loc` 是更正確的方式？

---

- [ ] **常見問題與除錯**

    *   **大小寫搞混 (`NameError: NameX Not Defined`)**
        *   Python **區分大小寫**！`my_variable` 和 `My_Variable` 是不同的變數。
        *   Pandas 的函式、方法、欄位名稱也都是區分大小寫的。
        *   檢查你的變數名稱、函式名稱、欄位名稱是否大小寫正確。
    *   **忘記匯入套件 (`NameError` 或 `AttributeError`)**
        *   使用任何套件的功能前，**必須**先使用 `import` 匯入。
        *   例如，你嘗試使用 `pd.read_csv()` 但沒有執行 `import pandas as pd`，就會出錯。
        *   看到錯誤訊息時，檢查一下你的程式碼開頭是否已經匯入所有需要的套件。
    *   **核心重新啟動 (Kernel Restart)**
        *   如果在 Jupyter Notebook 中重新啟動 (Restart) 了 Kernel，之前執行的程式碼、定義的變數、匯入的套件**都會被清除**。
        *   你需要從頭執行所有必要的程式碼 (包括匯入套件、讀取資料等)。
    *   **Axis 方向混淆**
        *   再次強調：`axis=0` 是**列**的方向 (垂直)，`axis=1` 是**行**的方向 (水平)。記不住就多查官方文件或筆記。
    *   **操作是否改變原始 DataFrame (`inplace`)**
        *   Pandas 許多操作（如排序 `sort_values`，但不包括 `.loc` 的賦值操作）預設會回傳一個**新的** DataFrame，而不是修改原始的。
        *   如果你確定想直接修改原始 DataFrame，可以使用 `inplace=True` 參數。
        *   但對於條件式修改，使用 `.loc` 是更推薦和正確的方式。

---

- [ ] **總結**

    *   本週我們學習了 Pandas 這個強大的 Python 資料處理工具。
    *   掌握了 Pandas 的核心結構：Series 和 DataFrame。
    *   學會了如何匯入 Pandas、讀取資料。
    *   學會了初步探索資料 (`.head()`) 和存取欄位。
    *   學習了 Pandas 的基本數據分析功能 (`.describe()`, `.corr()`)。
    *   學會了新增欄位和進行數學運算 (特別是 Axis 的概念)。
    *   學會了排序 (`.sort_values()`) 和分組 (`.groupby()`)。
    *   **特別強調了使用 `.loc` 進行精確選取和修改的重要性**！
    *   了解了一些常見問題和除錯方法。
    *   **課後：** 請務必花時間多練習，熟練今天教的操作。