WeHelp
Pandas 是 Python 用來做資料分析和處理的熱門工具,也是資料分析師的必備技能。
  1. 簡介、安裝、快速開始
  2. Series 單維度資料
  3. Series 實務案例
  4. DataFrame 雙維度資料
  5. DataFrame 實務案例
  6. 過濾資料的範例說明
  7. 缺失填補的範例說明
  8. 排序資料的範例說明
  9. CSV、Excel 檔案存取
  10. JSON 格式檔案存取
排序資料的範例說明
以下整理 Pandas 中「排序資料」以及「取得最前面或最後面資料」的常見用法,並附上實用技巧與完整範例。 --- # 1. 建立範例資料 ```python import pandas as pd import numpy as np df = pd.DataFrame({ "姓名": ["小明", "小華", "小美", "小強", "小安"], "年齡": [25, 30, 22, 28, 35], "部門": ["業務", "技術", "業務", "技術", "管理"], "薪資": [42000, 65000, 38000, 58000, 72000], "到職日": pd.to_datetime([ "2022-03-01", "2020-07-15", "2023-01-10", "2021-05-20", "2019-11-01" ]) }) print(df) ``` 輸出: ```text 姓名 年齡 部門 薪資 到職日 0 小明 25 業務 42000 2022-03-01 1 小華 30 技術 65000 2020-07-15 2 小美 22 業務 38000 2023-01-10 3 小強 28 技術 58000 2021-05-20 4 小安 35 管理 72000 2019-11-01 ``` --- # 2. 依單一欄位排序:`sort_values()` ## 2.1 由小到大排序 ```python result = df.sort_values(by="薪資") print(result) ``` 結果會按照薪資由低到高排列: ```text 姓名 年齡 部門 薪資 到職日 2 小美 22 業務 38000 2023-01-10 0 小明 25 業務 42000 2022-03-01 3 小強 28 技術 58000 2021-05-20 1 小華 30 技術 65000 2020-07-15 4 小安 35 管理 72000 2019-11-01 ``` `sort_values()` 預設為升冪排序,也就是由小到大。 --- ## 2.2 由大到小排序 ```python result = df.sort_values( by="薪資", ascending=False ) print(result) ``` `ascending=False` 表示降冪排序,也就是由大到小。 --- ## 2.3 依文字欄位排序 ```python result = df.sort_values(by="姓名") print(result) ``` 文字通常會按照字典順序或 Unicode 順序排列。 --- # 3. 依多個欄位排序 可以將欄位名稱放進串列中: ```python result = df.sort_values( by=["部門", "薪資"] ) print(result) ``` 這表示: 1. 先依照「部門」排序 2. 同一個部門內,再依照「薪資」排序 --- ## 3.1 不同欄位使用不同排序方向 例如: - 部門由小到大 - 薪資由大到小 ```python result = df.sort_values( by=["部門", "薪資"], ascending=[True, False] ) print(result) ``` `ascending` 的順序必須和 `by` 對應: ```python by=["部門", "薪資"] ascending=[True, False] ``` 代表: ```text 部門:升冪 薪資:降冪 ``` --- # 4. 排序後重新設定索引 排序後,原本的索引通常會保留: ```python result = df.sort_values(by="薪資") print(result.index) ``` 可能得到: ```text Index([2, 0, 3, 1, 4], dtype='int64') ``` 如果希望索引重新變成 `0, 1, 2, ...`,可以使用 `reset_index()`。 ```python result = ( df.sort_values(by="薪資") .reset_index(drop=True) ) print(result) ``` `drop=True` 表示不要把原索引保留成新的欄位。 --- ## 4.1 保留原始索引 如果不使用 `drop=True`: ```python result = df.sort_values(by="薪資").reset_index() print(result) ``` 原本的索引會變成一個名為 `index` 的新欄位。 這在需要追蹤原始資料位置時很有用。 --- # 5. `head()`:取得最前面的資料 ## 5.1 取得前 5 筆 ```python top5 = df.head() print(top5) ``` `head()` 預設取得前 5 筆資料。 --- ## 5.2 取得前 N 筆 ```python top3 = df.head(3) print(top3) ``` 也可以使用變數: ```python n = 2 result = df.head(n) ``` --- ## 5.3 先排序,再取得前幾名 例如:取得薪資最高的 3 人。 ```python top3_salary = ( df.sort_values(by="薪資", ascending=False) .head(3) ) print(top3_salary) ``` 這是非常常見的寫法: ```python df.sort_values("欄位名稱", ascending=False).head(N) ``` --- # 6. `tail()`:取得最後面的資料 ## 6.1 取得最後 5 筆 ```python last5 = df.tail() print(last5) ``` --- ## 6.2 取得最後 N 筆 ```python last2 = df.tail(2) print(last2) ``` --- ## 6.3 依日期排序後取得最新資料 假設要取得最近到職的 2 人: ```python latest = ( df.sort_values(by="到職日", ascending=False) .head(2) ) print(latest) ``` 也可以先由舊到新排序,再用 `tail()`: ```python latest = ( df.sort_values(by="到職日") .tail(2) ) print(latest) ``` 兩種方式都可以,但通常「降冪排序後搭配 `head()`」語意比較清楚。 --- # 7. `nlargest()` 與 `nsmallest()` 當目標是取得某個數值欄位的前幾名,可以使用: - `nlargest()`:最大值前 N 筆 - `nsmallest()`:最小值前 N 筆 ## 7.1 取得薪資最高的 3 筆 ```python result = df.nlargest(3, "薪資") print(result) ``` 等同於: ```python result = ( df.sort_values(by="薪資", ascending=False) .head(3) ) ``` --- ## 7.2 取得薪資最低的 2 筆 ```python result = df.nsmallest(2, "薪資") print(result) ``` 等同於: ```python result = ( df.sort_values(by="薪資", ascending=True) .head(2) ) ``` --- ## 7.3 同時依多個欄位判斷 ```python result = df.nlargest( 3, columns=["薪資", "年齡"] ) print(result) ``` 這表示先依薪資挑選,若薪資相同,再參考年齡。 --- # 8. 處理缺失值排序 建立含有缺失值的資料: ```python df_missing = pd.DataFrame({ "姓名": ["小明", "小華", "小美", "小強"], "分數": [85, np.nan, 92, 70] }) ``` ## 8.1 缺失值預設排在最後 ```python result = df_missing.sort_values(by="分數") print(result) ``` 通常 `NaN` 會被放在最後。 --- ## 8.2 將缺失值放在最前面 ```python result = df_missing.sort_values( by="分數", na_position="first" ) print(result) ``` `na_position` 可以是: ```python na_position="first" # 缺失值放最前面 na_position="last" # 缺失值放最後面,預設值 ``` --- # 9. 排序索引:`sort_index()` 除了依欄位排序,也可以依索引排序。 ```python df_index = df.sort_values(by="薪資") print(df_index) ``` 此時資料的索引順序可能是: ```text 2, 0, 3, 1, 4 ``` 若要依索引重新排序: ```python result = df_index.sort_index() print(result) ``` --- ## 9.1 索引降冪排序 ```python result = df.sort_index(ascending=False) print(result) ``` --- ## 9.2 Series 的索引排序 ```python s = pd.Series( [30, 10, 20], index=["C", "A", "B"] ) print(s.sort_index()) ``` 輸出: ```text A 10 B 20 C 30 dtype: int64 ``` --- # 10. 不修改原始 DataFrame 與 `inplace` ## 10.1 預設不會修改原始資料 ```python sorted_df = df.sort_values(by="薪資") # df 本身通常仍維持原本順序 ``` 這是 Pandas 比較建議的使用方式,因為可以保留原始資料。 --- ## 10.2 使用 `inplace=True` ```python df.sort_values( by="薪資", ascending=False, inplace=True ) ``` 這會直接修改 `df`。 不過在實務上,通常更建議: ```python df = df.sort_values( by="薪資", ascending=False ) ``` 原因是: - 程式碼較容易追蹤 - 不容易意外修改原始資料 - 適合連續使用方法串接 - `inplace=True` 並不一定能帶來實質效能優勢 --- # 11. 使用 `key` 進行自訂排序 有時候不想直接按照原始值排序,而是希望先轉換後再排序。 ## 11.1 不分大小寫排序 ```python df_name = pd.DataFrame({ "name": ["bob", "Alice", "charlie", "alice"] }) result = df_name.sort_values( by="name", key=lambda col: col.str.lower() ) print(result) ``` 這樣會先將文字轉成小寫,再進行排序。 --- ## 11.2 依文字長度排序 ```python result = df_name.sort_values( by="name", key=lambda col: col.str.len() ) print(result) ``` --- ## 11.3 依中文字自訂順序 假設部門有特定順序: ```python department_order = ["管理", "技術", "業務"] df_order = df.copy() df_order["部門"] = pd.Categorical( df_order["部門"], categories=department_order, ordered=True ) result = df_order.sort_values(by="部門") print(result) ``` 這樣排序順序會依照: ```text 管理 → 技術 → 業務 ``` 而不是按照文字排序。 --- # 12. 群組內取得前幾名 例如:每個部門取得薪資最高的人。 ```python result = ( df.sort_values( by=["部門", "薪資"], ascending=[True, False] ) .groupby("部門") .head(1) ) print(result) ``` 說明: 1. 先依部門排序 2. 每個部門內薪資由高到低 3. `groupby("部門").head(1)` 取每組第一筆 --- ## 12.1 每個部門取薪資最高的 2 人 ```python result = ( df.sort_values( by=["部門", "薪資"], ascending=[True, False] ) .groupby("部門") .head(2) ) print(result) ``` 這個技巧常用於: - 每個分類取前 N 名 - 每個客戶取最新幾筆交易 - 每個地區取銷售額最高的產品 - 每個群組取評分最高的資料 --- # 13. 使用 `groupby().nlargest()` 也可以使用 `groupby()` 搭配 `nlargest()`: ```python result = ( df.groupby("部門")["薪資"] .nlargest(2) ) print(result) ``` 輸出會是帶有多層索引的 Series。 如果希望取得完整資料,可以使用: ```python result = ( df.loc[ df.groupby("部門")["薪資"] .nlargest(2) .reset_index()["level_1"] ] ) print(result) ``` 不過對初學者而言,這種情況使用: ```python df.sort_values(...).groupby(...).head(...) ``` 通常比較直觀。 --- # 14. 取得排序後的第一筆或最後一筆 ## 14.1 取得排序後的第一筆 ```python result = ( df.sort_values(by="薪資", ascending=False) .iloc[0] ) print(result) ``` `iloc[0]` 會回傳一個 Series。 如果希望結果仍然是 DataFrame,可以使用: ```python result = ( df.sort_values(by="薪資", ascending=False) .head(1) ) ``` --- ## 14.2 取得排序後的最後一筆 ```python result = ( df.sort_values(by="薪資") .iloc[-1] ) print(result) ``` 或: ```python result = ( df.sort_values(by="薪資") .tail(1) ) ``` 差異如下: ```python .iloc[0] # 回傳 Series .head(1) # 回傳 DataFrame ``` --- # 15. `idxmax()` 與 `idxmin()` 如果只想找到最大值或最小值所在的索引,可以使用: ```python max_index = df["薪資"].idxmax() min_index = df["薪資"].idxmin() print(max_index) print(min_index) ``` 再使用 `.loc[]` 取得完整資料: ```python highest_salary = df.loc[df["薪資"].idxmax()] lowest_salary = df.loc[df["薪資"].idxmin()] print(highest_salary) print(lowest_salary) ``` 這種方法適合只需要單一最大值或最小值的情況。 --- ## 15.1 最大值有重複時 `idxmax()` 只會回傳第一筆最大值。 如果想取得所有並列最高薪資的人: ```python max_salary = df["薪資"].max() result = df[df["薪資"] == max_salary] print(result) ``` 或使用: ```python result = df[ df["薪資"].eq(df["薪資"].max()) ] ``` --- # 16. 常見技巧整理 ## 16.1 依欄位升冪排序 ```python df.sort_values("薪資") ``` ## 16.2 依欄位降冪排序 ```python df.sort_values("薪資", ascending=False) ``` ## 16.3 多欄位排序 ```python df.sort_values( by=["部門", "薪資"], ascending=[True, False] ) ``` ## 16.4 取得前 N 筆 ```python df.head(3) ``` ## 16.5 取得最後 N 筆 ```python df.tail(3) ``` ## 16.6 取得數值最高的 N 筆 ```python df.nlargest(3, "薪資") ``` ## 16.7 取得數值最低的 N 筆 ```python df.nsmallest(3, "薪資") ``` ## 16.8 排序後重新建立索引 ```python df.sort_values("薪資").reset_index(drop=True) ``` ## 16.9 依索引排序 ```python df.sort_index() ``` ## 16.10 每個群組取前 N 筆 ```python ( df.sort_values( ["部門", "薪資"], ascending=[True, False] ) .groupby("部門") .head(2) ) ``` --- # 17. 一個完整實例 取得「每個部門薪資最高的 1 位員工」,並將結果重新排序及整理索引: ```python result = ( df.sort_values( by=["部門", "薪資"], ascending=[True, False] ) .groupby("部門", as_index=False) .head(1) .sort_values(by="薪資", ascending=False) .reset_index(drop=True) ) print(result) ``` 執行流程: 1. 依部門分組 2. 每個部門內薪資由高到低排序 3. 每個部門取第一筆 4. 將結果依薪資由高到低排序 5. 重新建立索引 --- # 18. 注意事項 ## 欄位名稱不存在 ```python df.sort_values(by="不存在的欄位") ``` 會產生 `KeyError`,因此要確認欄位名稱: ```python print(df.columns) ``` --- ## 欄位型別要正確 日期欄位最好先轉換成日期格式: ```python df["到職日"] = pd.to_datetime(df["到職日"]) ``` 如果日期被當作文字,排序可能只按照字串順序處理。 --- ## 數字欄位不要誤存成文字 例如: ```python "100", "20", "3" ``` 文字排序可能會得到: ```text 100, 20, 3 ``` 正確的數字排序應先轉型: ```python df["分數"] = pd.to_numeric(df["分數"], errors="coerce") ``` --- ## 排序不一定會修改原始資料 ```python sorted_df = df.sort_values("薪資") ``` 這只會產生新的 DataFrame。若要保存結果,必須指定給變數,或使用 `inplace=True`。 --- 簡單來說: ```python # 排序 df.sort_values("薪資") # 由大到小排序 df.sort_values("薪資", ascending=False) # 前 N 筆 df.head(N) # 後 N 筆 df.tail(N) # 最大的 N 筆 df.nlargest(N, "薪資") # 最小的 N 筆 df.nsmallest(N, "薪資") ``` 這幾個方法已經可以涵蓋大部分 Pandas 的排序與取資料需求。
相關學習地圖、教學課程
Python 資料工程
從 0 開始,成為資料工程師的學習路徑。