iT邦幫忙

2025 iThome 鐵人賽

DAY 9
0

as title 今天的主題是index和排序。

Index

index是指欄與列的標籤系統,在運算、join/merge前,pandas會用索引標籤來做資料對齊。,資料對齊是什麼呢?就是欄位和索引會先進行配對以後再做運算。詳細等講到merge再來說。今天先focus在index上。

  • 列索引:

    • dataframe.index
    • dataframe.set_index的這個index也是指列索引
    • 沒有set index: RangeIndex(start=0, stop=10, step=1)
    • 有set index: Index(['Mary', 'John','Peter'], dtype='object', name='name')
  • 欄索引:

    • dataframe.columns
    • 依照欄位設定產生的索引物件
    • Index(['name', 'grade'], dtype='object')

好的索引讓你上天堂,不好的索引就我思故我在了。

https://ithelp.ithome.com.tw/upload/images/20250922/201786317V8L1pI9cW.png

笛卡兒乘積

當兩個dataframe或series一起運算時,pandas會先做一個資料對齊的動作(語言癌啊),要是兩邊的欄位不一致就有可能因為迪卡兒乘積導致index爆炸。

資料可能會出現以下狀況,

  • 索引唯一 → OK
  • 索引重複、順序相同、內容長度相同 → OK
  • 索引重複、順序相同、內容長度不同 → 笛卡兒乘積
  • 索引重複、順序不同、內容不管相不相同 → 笛卡兒乘積

所以最好的方式是確定索引唯一
df.index.is_unique

不唯一怎麼辦,讓它唯一
s1 = s1[~s1.index.duplicated(keep="first")]

keep的用法

  • first:保留第一列資料
  • last: 保留最後一列資料
  • false: 刪除所有重複列
s1 = pd.Series([1, 2, 6], index=["A", "A", "A"])
s2 = pd.Series([10, 20], index=["A", "A"])
print(s1 + s2)

s1 = s1[~s1.index.duplicated(keep="first")]
s2 = s2[~s2.index.duplicated(keep="first")]
print(s1 + s2)

還有另一種方法也可以讓它唯一
df.reset_index(drop=True|False)
意思就是把重設index,改用位置型的RangeIndex取代

  • drop為true:直接把index欄刪掉
  • drop為false:讓原本的index欄變成一個普通欄位
df = pd.DataFrame({"x":[1,2,3]}, index=["A","B","C"])
df = pd.DataFrame({"x":[1,2,3]}, index=["A","B","C"])

drop為true的結果:

row index x
0 1
1 2
2 3

drop為false的結果:

row index index x
0 A 1
1 B 2
2 C 3

排序

排序也是必備良藥,畢竟誰用excel沒用過排序呢~
排序分為

  • 資料的排序 (by欄/列/索引資料)
  • 欄位名稱的排序

data排序

sort_values()

依欄位排序:df.sort_values(column,ascending=False)

# 單欄排序
df.sort_values("score")

# 多欄排序
df.sort_values(["score","age"], ascending=[False,True])
df.sort_values("score")                        # NaN 預設在最後
df.sort_values("score", na_position="first")   # NaN 放前面

# 抓出分數最高的100筆, ascending為False是由大到小排序
df.sort_values("score", ascending=False).head(100)
# 抓出分數最低的100筆, ascending預設是True所以也可以不用賦值, 是由小到大排序
df.sort_values("score").head(100)

sort_values也常搭配drop_duplicates組合拳。

sort_index()

依列索引排序:df.sort_index(ascending=False)

df = pd.DataFrame({
    "name":["Bojack","Dan","Todd"],
    "score":[80,95,70]
}, index=[2,0,1])

print(df.sort_index())       # 預設升冪
print(df.sort_index(ascending=False))  # 降冪

抓最大/小的幾筆

雖然之前有講過了,但還是再帶一下,好用值得一提再提

  • nsmallest(count, 'column_name')
  • nlargest(count, 'column_name)

找到最大值(及它的列資訊)

  • by欄位找最大值
    df["Model Year"].max()
  • by欄位找最大值的索引
    df["Model Year"].idxmax()
  • by欄位回傳最大值的列資訊
    df.loc[df["Model Year"].idxmax(), :]
  • 回傳所有數值型態欄位的最大值
    df.select_dtypes(include="number").idxmax()

idmax是個很強大的function

  • 如果有設定index,就會回傳index label,沒有的話就會回傳location的index。
  • 給單個欄位名稱,回傳單個index。
  • 給欄位陣列或是select_dtypes,就會列出每個column的index。

好用到就離譜,只想說帥~好帥~
最小值就是把所有的max換成min,用min()、idxmin(),我就不再浪費it邦的空間複述了。

欄位名稱排序

剛剛的sort_index,只要加個參數 axis=1,就可以做欄位名稱的排序了。
依欄位名稱排序:df.sort_index(axis=1, ascending=False)

但是這不符合實際應用場景啊。要以data有意義user要的方式排列,有以下幾種方法。

  • 手排檔土法練鋼
    df = df[["a","b","c"]]

  • 部分優先, 剩下接後面

first_cols = ["seq","name"]
df = df[first_cols + [col for col in df.columns if col not in first_cols]]
  • 自訂函數
    df = df[sorted(df.columns, key=lambda x: (len(x), x))]
  • 正則式
frist = [c for c in df.columns if re.match("^x", c)]
left = [c for c in df.columns if c not in front]
df = df[frist + left]

好了,以上。打完收工,居然能在十一點前送出,真是太感人了。

下集預告:排序排完就來到分組groupby了!有可能一天講不完,畢竟書裡的第九章,它花了74頁才講完。沒關係不糾結,一天講不完就兩天。時到時擔當。


上一篇
Day7: 資料讀寫 - JSON/關於orientation
下一篇
Day9: GroupBy...的上集 | agg()
系列文
從零開始Pandas-外加一點Matplotlib11
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言