groupby是Pandas在資料分析中最常用的函數之一。它用于根據給定列中的不同值對資料點(即行)進行分組,分組後的資料可以計算生成組的聚合值。
如果我們有一個包含汽車品牌和價格資訊的資料集,那麼可以使用groupby功能來計算每個品牌的平均價格。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5CMykDN5gDOmJDO1EGMilDNzYzXzMTN1IDM1EzLcBTMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
在本文中,我們将使用25個示例來詳細介紹groupby函數的用法。這25個示例中還包含了一些不太常用但在各種任務中都能派上用場的操作。
這裡使用的資料集是随機生成的,我們把它當作一個銷售的資料集。
import pandas as pd
sales = pd.read_csv("sales_data.csv")
sales.head()
1、單列聚合
我們可以計算出每個店鋪的平均庫存數量如下:
sales.groupby("store")["stock_qty"].mean()
#輸出
store
Daisy 1811.861702
Rose 1677.680000
Violet 14622.406061
Name: stock_qty, dtype: float64
2、多列聚合
在一個操作中進行多個聚合。以下是我們如何計算每個商店的平均庫存數量和價格。
sales.groupby("store")[["stock_qty","price"]].mean()
3、多列多個聚合
我們還可以使用agg函數來計算多個聚合值。
sales.groupby("store")["stock_qty"].agg(["mean", "max"])
4、對聚合結果進行命名
在前面的兩個示例中,聚合清單示什麼還不清楚。例如,“mean”并沒有告訴我們它是什麼的均值。在這種情況下,我們可以對聚合的結果進行命名。
sales.groupby("store").agg(
avg_stock_qty = ("stock_qty", "mean"),
max_stock_qty = ("stock_qty", "max")
)
要聚合的列和函數名需要寫在元組中。
5、多個聚合和多個函數
sales.groupby("store")[["stock_qty","price"]].agg(["mean", "max"])
6、對不同列的聚合進行命名
sales.groupby("store").agg(
avg_stock_qty = ("stock_qty", "mean"),
avg_price = ("price", "mean")
)
7、as_index參數
如果groupby操作的輸出是DataFrame,可以使用as_index參數使它們成為DataFrame中的一列。
sales.groupby("store", as_index=False).agg(
avg_stock_qty = ("stock_qty", "mean"),
avg_price = ("price", "mean")
)
8、用于分組的多列
就像我們可以聚合多個列一樣,我們也可以使用多個列進行分組。
sales.groupby(["store","product_group"], as_index=False).agg(
avg_sales = ("last_week_sales", "mean")
).head()
每個商店和産品的組合都會生成一個組。
9、排序輸出
可以使用sort_values函數根據聚合列對輸出進行排序。
sales.groupby(["store","product_group"], as_index=False).agg( avg_sales = ("last_week_sales", "mean")
).sort_values(by="avg_sales", ascending=False).head()
這些行根據平均銷售值按降序排序。
10、最大的Top N
max函數傳回每個組的最大值。如果我們需要n個最大的值,可以用下面的方法:
sales.groupby("store")["last_week_sales"].nlargest(2)
store
Daisy 413 1883
231 947
Rose 948 883
263 623
Violet 991 3222
339 2690
Name: last_week_sales, dtype: int64
11、最小的Top N
與最大值相似,也可以求最小值
sales.groupby("store")["last_week_sales"].nsmallest(2)
12、第n個值
除上面2個以外,還可以找到一組中的第n個值。
sales_sorted = sales.sort_values(by=["store","last_month_sales"], ascending=False, ignore_index=True)
找到每個店鋪上個月銷售排名第五的産品如下:
sales_sorted.groupby("store").nth(4)
輸出包含每個組的第5行。由于行是根據上個月的銷售值排序的,是以我們将獲得上個月銷售額排名第五的行。
13、第n個值,倒排序
也可以用負的第n項。例如," nth(-2) "傳回從末尾開始的第二行。
sales_sorted.groupby("store").nth(-2)
14、唯一值
unique函數可用于查找每組中唯一的值。例如,可以找到每個組中唯一的産品代碼如下:
sales.groupby("store", as_index=False).agg(
unique_values = ("product_code","unique")
)
15、唯一值的數量
還可以使用nunique函數找到每組中唯一值的數量。
sales.groupby("store", as_index=False).agg(
number_of_unique_values = ("product_code","nunique")
)
16、Lambda表達式
可以在agg函數中使用lambda表達式作為自定義聚合操作。
sales.groupby("store").agg(
total_sales_in_thousands = (
"last_month_sales",
lambda x: round(x.sum() / 1000, 1)
)
)
17、apply函數
使用apply函數将Lambda表達式應用到每個組。例如,我們可以計算每家店上周銷售額與上個月四分之一銷售額的內插補點的平均值,如下:
sales.groupby("store").apply(
lambda x: (x.last_week_sales - x.last_month_sales / 4).mean()
)
store
Daisy 5.094149
Rose 5.326250
Violet 8.965152
dtype: float64
18、dropna
預設情況下,groupby函數忽略缺失值。如果用于分組的列中缺少一個值,那麼它将不包含在任何組中,也不會單獨顯示。是以可以使用dropna參數來改變這個行為。
讓我們首先添加一個缺少存儲值的新行。
sales.loc[1000] = [None, "PG2", 10000, 120, 64, 96, 15, 53]
然後計算帶有dropna參數和不帶有dropna參數的每個商店的平均價格,以檢視差異。
sales.groupby("store")["price"].mean()
store
Daisy 69.327426
Rose 60.513700
Violet 67.808727
Name: price, dtype: float64
看看設定了缺失值參數的結果:
sales.groupby("store", dropna=False)["price"].mean()
store
Daisy 69.327426
Rose 60.513700
Violet 67.808727
NaN 96.000000
Name: price, dtype: float64
groupby函數的dropna參數,使用pandas版本1.1.0或更高版本。
19、求組的個數
有時需要知道生成了多少組,這可以使用ngroups。
sales.groupby(["store", "product_group"]).ngroups
18
在商店和産品組列中有18種不同值的不同組合。
20、獲得一個特定分組
get_group函數可擷取特定組并且傳回DataFrame。
例如,我們可以獲得屬于存儲“Daisy”和産品組“PG1”的行如下:
aisy_pg1 = sales.groupby(
["store", "product_group"]).get_group(("Daisy","PG1")
)
daisy_pg1.head()
21、rank函數
rank函數用于根據給定列中的值為行配置設定秩。我們可以使用rank和groupby函數分别對每個組中的行進行排序。
sales["rank"] = sales.groupby("store"["price"].rank(
ascending=False, method="dense"
)
sales.head()
22、累計操作
們可以計算出每組的累計總和。
import numpy as npdf = pd.DataFrame(
{
"date": pd.date_range(start="2022-08-01", periods=8, freq="D"),
"category": list("AAAABBBB"),
"value": np.random.randint(10, 30, size=8)
}
)
我們可以單獨建立一個列,包含值列的累計總和,如下所示:
df["cum_sum"] = df.groupby("category")["value"].cumsum()
23、expanding函數
expanding函數提供展開轉換。但是對于展開以後的操作還是需要一個累計函數來堆區操作。例如它與cumsum 函數一起使用,結果将與與sum函數相同。
df["cum_sum_2"] = df.groupby(
"category"
)["value"].expanding().sum().values
24、累積平均
利用展開函數和均值函數計算累積平均。
df["cum_mean"] = df.groupby(
"category"
)["value"].expanding().mean().values
25、展開後的最大值
可以使用expand和max函數記錄組目前最大值。
df["current_highest"] = df.groupby(
"category"
)["value"].expanding().max().values