博客 / 詳情

返回

10個Pandas的高級技巧

Pandas是我們最常用的數據處理Python庫之一。儘管您可能已經與它共事多年,但可能還有許多您尚未探索的實用方法。我將向您展示一些可能未曾聽説但在數據整理方面非常實用的方法。

我目前日常使用的是pandas 2.2.0,這是本文時可用的最新版本。

 import pandas as pd
 import numpy as np
 
 print(pd.__version__)

1、agg

你可能已經熟悉使用pandas進行聚合操作,比如使用sum或min等方法。可能也已經結合groupby使用過這些方法。agg方法可以在DataFrame上執行一個或多個聚合操作。

通過將字典傳遞給agg方法,指示要為DataFrame的每一列計算哪些聚合操作(sum、mean、max等)。字典的鍵表示我們要對其執行聚合操作的列,而值表示我們要執行的操作。

 data = {
     "A": [1, 2, 3, 4],
     "B": [5, 6, 7, 8],
     "C": [9, 10, 11, 12],
 }
 
 df = pd.DataFrame(data)
 
 df.agg({"A": "sum", "B": "mean", "C": "max"})

agg並不僅限於為每列傳遞單個操作。在下一段代碼中可以計算列A總和和平均值

 df.agg({"A": ["sum", "mean"], "B": "mean", "C": "max"})

在生成的DataFrame中,可以觀察到一些NaN值,這些值對應於字典中沒有請求的列和操作的組合。

下面我們添加一個分組列。要計算每個兩個組內所有三列的平均值和總和。

 data = {
     "group": [1, 1, 2, 2],
     "A": [1, 2, 3, 4],
     "B": [5, 6, 7, 8],
     "C": [9, 10, 11, 12],
 }
 
 df = pd.DataFrame(data)
 
 df.groupby("group").agg(["mean", "sum"])

最後,就是我們可以將最終生成的列重新命名:

 df.groupby("group").agg(
     avg_a=("A", "mean"),
     sum_a=("A", "sum"),
     min_c=("C", "min"),
 )

2、assign

assign方法用於創建帶有附加列的新DataFrame,並根據現有列或操作分配值。

 df = pd.DataFrame({"Value": [10, 15, 20, 25, 30, 35]})
 df.assign(value_cat=np.where(df["Value"] > 20, "high", "low"))

這種方法在鏈式操作中最有用,因為我們不一定對中間步驟感興趣,並且並不想將中間結果添加到原始DataFrame中。

 df.assign(value_cat=np.where(df["Value"] > 20, "high", "low")).groupby(
     "value_cat"
 ).mean()

3、combine_first

combine_first方法用於組合兩個Series(或DataFrame中的列),從第一個Series中選擇值,並用第二個Series中的相應值填充任何缺失的值。

如果你對SQL熟悉的話,那麼pandas的combine_first方法類似於SQL中的COALESCE函數。

 s1 = pd.Series([1, 2, np.nan, 4, np.nan, 6])
 s2 = pd.Series([10, np.nan, 30, 40, np.nan, 60])
 
 s1.combine_first(s2)

可以看到s1中缺失的值被s2的值填充。如果s2也是缺失值,則結果為缺失值。這種方法也可以用於DataFrame的列。

如果我們希望使用2列以上的列來更新缺失的值,我們也可以鏈接combine_firstmethods。

4、cumsum / cummin / cummax / cumprod

cumsum、cummin、cummax和cumprod方法用於計算Series或DataFrame中元素的累積和、最小值、最大值和乘積。

 data = {
     'A': [3, 1, 2, 0.5, 5, 10],
 }
 
 df = pd.DataFrame(data)
 df["cumsum"] = df["A"].cumsum()
 df["cummin"] = df["A"].cummin()
 df["cummax"] = df["A"].cummax()
 df["cumprod"] = df["A"].cumprod()
 df

5、cut / qcut

cut函數將數據劃分為相同寬度的桶。這意味着每個桶都有相同的範圍,但是每個桶中的數據點數量可能不同。

 df = pd.DataFrame(
     {
         "name": ["Alice", "Bob", "Charlie", "Dylan", "Eve", "Frank"],
         "years_of_exp": [10, 2, 0, 5, 6, 8],
     }
 )
 
 pd.cut(df["years_of_exp"], bins=3)

cut函數將所有觀測值分類到三個長度相等(長度約為3.33)的桶中。

這裏需要強調下區間符號。

 [0,10]:區間兩邊都閉合,即同時包含0和10
 (0,10):間隔兩邊都不閉合,即不包括0和10
 [0,10):區間左側閉合,表示包含0,但不包含10。

我們可以定義桶的區間

 exp_bins = [0, 2, 5, 10]
 pd.cut(df["years_of_exp"], bins=exp_bins)

在輸出中看到一個NaN值。這是因為最低值不包括在範圍內。我們可以通過將include_lowest設置為True來解決這個問題。

還可以為桶分配自定義標籤名稱,這在特徵工程時特別有用

 exp_labels = ["Junior level", "Mid level", "Senior level"]
 pd.cut(df["years_of_exp"], bins=exp_bins, include_lowest=True, labels=exp_labels)

qcut函數根據分位數將數據劃分為桶。這確保了每個桶具有大致相同數量的數據點。

 pd.qcut(df["years_of_exp"], q=3)

使用qcut每個桶中都有2個值。cut根據區間劃分數據,而qcut則根據分位數劃分數據。

6、duplicate / drop_duplicate

duplicate方法返回一個boolean Series,指示DataFrame中的每個元素是否重複(True)或不重複(False)。

 data = {"A": [1, 2, 2, 3, 4, 4], "B": ["x", "y", "y", "z", "w", "w"]}
 df = pd.DataFrame(data)
 
 df.duplicated()

duplicate的默認設置 keep="first" ,保留第一個匹配的值,並將所有後續的觀測值標記為duplicate.

也可以使用 keep="last" 保留最後的值,還可以使用keep=False 將所有的重複值標記為True

 df.duplicated(keep=False)

最後使用drop_duplduplicate方法直接刪除重複項。drop_duplduplicate方法也可以設置keep參數

 df.drop_duplicates()

7、isin

isin方法用於篩選Series和dataframe,該方法返回一個布爾Series,顯示列中的每個值是否在指定值範圍內。

 data = {
     "Name": ["Alice", "Bob", "Charlie", "David", "Eve"],
     "Value": [1, 1, 1, 2, 2],
 }
 
 df = pd.DataFrame(data)
 
 selected_names = ["Alice", "David", "Eve"]
 df[df["Name"].isin(selected_names)]

8、merge_ordered

merge_ordered函數用來合併兩個dataframe。當我們有兩個具有順序的dataframe,並且希望在保持索引的順序的同時合併它們時(比如説時間序列),這個函數特別有用。

 df1 = pd.DataFrame(
     {
         "date": pd.date_range(start="2022-01-01", periods=5)[::-1],
         "value_df1": [10, 15, 20, 25, 30],
     }
 )
 
 df2 = pd.DataFrame(
     {
         "date": pd.date_range(start="2022-01-03", periods=4)[::-1],
         "value_df2": [100, 150, 250, 300],
     }
 )
 
 pd.merge_ordered(df1, df2, on="date", fill_method="ffill")

merge_ordered中連接的默認是outer join,所以fill_method需要設置一種方法來填充缺失值。

9、pct_change

pct_change用於計算Series或DataFrame中當前元素和先前元素之間的百分比變化。它用於分析價值隨時間變化的百分比,特別是在金融時間序列數據中,例如股票價格。

 data = {
     "date": pd.date_range(start="2022-01-01", end="2022-01-05"),
     "price": [100, 105, 98, 110, 120],
 }
 
 df = pd.DataFrame(data).set_index("date")
 
 df["price"].pct_change()

10、select_dtypes

select_dtypes用於根據數據類型篩選DataFrame中的列。我們可以使用它來選擇具有特定數據類型的列,例如數字類型(int64、float64)、對象類型(str、object)、布爾類型或日期時間類型等。

我們選擇整數列和浮點列,即數字列。

 data = {
     "name": ["Alice", "Bob", "Charlie"],
     "age": [25, 30, 22],
     "salary": [50000.0, 60000.0, 45000.0],
     "date_joined": ["2022-01-01", "2022-02-15", "2021-12-10"],
     "remote_worker": [True, False, True]
 }
 
 df = pd.DataFrame(data)
 
 df.select_dtypes(include=["int64", "float64"])

或者可以直接這樣寫

 df.select_dtypes(include="number")

select_dtypes,還可以指定要排除哪些數據類型

 df.select_dtypes(exclude="object")

總結

pandas是一個非常龐大的庫,我們最常用的只是其中的一些方法,可能還有許多尚未探索的實用方法。希望本文介紹的10各高級技巧可以幫你更有效地處理各種數據,更靈活地滿足各種數據處理需求。

https://avoid.overfit.cn/post/2baf150e08a1418584b03f804de21b6d

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.