在使用 Pandas 進行數據分析時,groupby
配合 size
是計算分組數量的常用組合。但你是否遇過明明是相同的操作,結果卻相差一倍的情況?本文將深入解析 size
屬性和 size()
方法的差異,幫你避開這個常見陷阱。
import pandas as pd
data = {'id': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'name': ['John', 'Anna', 'John', 'Anna',
'John', 'Anna', 'John', 'Anna',
'John', 'Anna']}
df = pd.DataFrame(data)
duplicates = df.duplicated(subset=['name'])
df_dup = df[duplicates] # 只保留重複的資料
John(Anna)出現了5次,重複了4次
輸出結果:
![Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王](https://savingking.com.tw/wp-content/uploads/2025/06/20250609143758_0_53821c.png)
現在,讓我們試試三種看似相同的計數方式:
# 方法 1:GroupBy.size() 方法
print(df_dup.groupby('name').size())
# Anna 4
# John 4
# 方法 2:遍歷並使用 size 屬性
for name, group in df_dup.groupby('name'):
print(f"{name}: {group.size}")
# Anna: 8
# John: 8
# 方法 3:先選列再分組
for name, group in df_dup.groupby('name')['name']:
print(f"{name}: {group.size}")
# Anna: 4
# John: 4
輸出結果:
![Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王](https://savingking.com.tw/wp-content/uploads/2025/06/20250609144842_0_9d37ac.png)
為什麼方法 2 的結果是 8 而不是 4?讓我們深入了解背後的原因。
![Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王](https://savingking.com.tw/wp-content/uploads/2025/06/20250609205535_0_548055.png)
核心概念解析
1. size 屬性 vs size() 方法
在 Pandas 中,size
既可以是屬性也可以是方法,取決於使用的物件:
![Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王](https://savingking.com.tw/wp-content/uploads/2025/06/20250609145052_0_1000c9.png)
size 屬性(對df與Series作用) 與
size()方法(對GroupBy物件作用,包括
DataFrameGroupBy與
SeriesGroupBy)
# DataFrame 的 size 屬性
df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
print(df.size) # 6 (3行 × 2列)
print("傳說中的分隔線".center(20,"="))
# Series 的 size 屬性
s = pd.Series([1, 2, 3])
print(s.size) # 3
print("傳說中的分隔線".center(20,"="))
# GroupBy 的 size() 方法
grouped = df.groupby('A')
print(grouped.size()) # 返回 Series,顯示每組數量
輸出結果:
![Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王](https://savingking.com.tw/wp-content/uploads/2025/06/20250609145330_0_be3f34.png)
2. DataFrameGroupBy vs SeriesGroupBy
當你進行分組操作時,根據操作對象的不同,會產生不同類型的 GroupBy 物件:
# DataFrameGroupBy:對整個 DataFrame 分組
grouped_df = df.groupby('name')
print(type(grouped_df)) # DataFrameGroupBy
# SeriesGroupBy:對單一列分組
grouped_series = df['name'].groupby(df['name'])
# 或者
grouped_series = df.groupby('name')['name']
print(type(grouped_series)) # SeriesGroupBy
輸出結果:
![Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王](https://savingking.com.tw/wp-content/uploads/2025/06/20250609145537_0_d1e05c.png)
關鍵差異詳解
讓我們回到最初的問題,為什麼遍歷時會得到不同的結果:
情況 1:DataFrameGroupBy(結果為 8)
for name, group in df_dup.groupby('name'):
print(f"\n{name} 組的內容:")
print(group)
print(f"類型:{type(group)}")
print(f"shape:{group.shape}")
print(f"size:{group.size}")
輸出結果:
![Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王](https://savingking.com.tw/wp-content/uploads/2025/06/20250609145706_0_071642.png)
情況 2:SeriesGroupBy(結果為 4)
![Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王](https://savingking.com.tw/wp-content/uploads/2025/06/20250609145816_0_084c67.png)
實用技巧總結
1. 計算每組數量的正確方式
#
推薦:使用 GroupBy.size() 方法
result = df.groupby('name').size()
#
推薦:使用 value_counts()
result = df['name'].value_counts()
#
小心:遍歷時要用 len() 而不是 .size
for name, group in df.groupby('name'):
count = len(group) # 正確
# count = group.size # 錯誤(會得到總元素數)
快速檢查類型
grouped = df.groupby('name')
# 檢查是否為 GroupBy 物件
print(hasattr(grouped, 'size')) # False (沒有 size 屬性)
print(callable(getattr(grouped, 'size', None))) # True (有 size() 方法)
# 檢查遍歷時的內容
for name, group in grouped:
print(f"Group 類型:{type(group)}")
break
輸出結果:
![Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王](https://savingking.com.tw/wp-content/uploads/2025/06/20250609150234_0_9ea0dd.png)
常見使用場景
# 場景 1:統計重複值數量
duplicates_count = df[df.duplicated()].groupby('name').size()
# 場景 2:計算每組佔比
group_sizes = df.groupby('category').size()
percentages = group_sizes / len(df) * 100
# 場景 3:篩選大於特定數量的組
large_groups = group_sizes[group_sizes > 10]
輸出結果:
![Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王](https://savingking.com.tw/wp-content/uploads/2025/06/20250609150639_0_415cd2.png)
重點整理
- DataFrame/Series 的
size
是屬性(不用括號),返回總元素數 - GroupBy 的
size()
是方法(要用括號),返回每組行數 - 遍歷 DataFrameGroupBy 得到的是 DataFrame,其 size = 行數 × 列數
- 遍歷 SeriesGroupBy 得到的是 Series,其 size = 元素個數
- 計算分組數量時,優先使用
GroupBy.size()
方法或value_counts()
- 若確定資料為DataFrame/Series,
使用len()或.shape[0]計算rows比較不會錯誤
結語
理解 Pandas 中 size
的不同用法,能幫助你避免在數據分析中產生錯誤的計數結果。記住這個簡單的規則:
- 看到 GroupBy?用
.size()
方法 - 看到 DataFrame/Series?
.size
是屬性
下次當你的分組計數結果看起來不對時,
先檢查你是在使用 size
屬性還是 size()
方法!
作用的對象是DataFrame, Series還是GroupBy對象?
特別需要區分DataFrame 與 DataFrameGroupBy
推薦hahow線上學習python: https://igrape.net/30afN
.duplicated()
的作用是標記出 DataFrame 或 Series 中的重複行,但它只標記從第二次出現開始的重複項,不會將第一次出現的項目標記為重複。因此,第一次出現的項目不會被視為重複,結果中確實會少一次。
解釋 .duplicated()
.duplicated()
返回的是一個布林值序列,表示每一行(或每個值)是否是重複項。- 默認情況下,只會標記從第二次開始的重複項為
True
,第一次出現的項標記為False
。
範例
建立範例數據
import pandas as pd
# 建立範例數據
data = {'name': ['Alice', 'Bob', 'Alice', 'Charlie', 'Bob', 'Alice']}
df = pd.DataFrame(data)
print(df)
輸出:
![Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王](https://savingking.com.tw/wp-content/uploads/2025/06/20250609160506_0_6520e8.png)
使用 .duplicated()
![Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王](https://savingking.com.tw/wp-content/uploads/2025/06/20250609160609_0_bce225.png)
解釋:
- 第 0 行(
Alice
)是第一次出現,因此標記為False
。 - 第 1 行(
Bob
)是第一次出現,因此標記為False
。 - 第 2 行(
Alice
)是重複項,因此標記為True
。 - 第 3 行(
Charlie
)是第一次出現,因此標記為False
。 - 第 4 行(
Bob
)是重複項,因此標記為True
。 - 第 5 行(
Alice
)是重複項,因此標記為True
。
為什麼「少一次」?
因為 .duplicated()
的邏輯是:
- 第一次出現的項目被認為是唯一的,標記為
False
。 - 只有從第二次開始出現的項目,才會被標記為
True
。
因此,當你只看 .duplicated()
的結果時,重複的項目中確實會「少一次」,即第一次出現的項目不會算入重複。
如果需要標記所有重複項
如果你希望包括第一次出現的項目也標記為重複,可以使用以下方法:
![Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王](https://savingking.com.tw/wp-content/uploads/2025/06/20250609160719_0_11d4e3.png)
解釋:
keep=False
表示所有重複項,包括第一次出現的項目,都會被標記為True
。
總結
.duplicated()
默認只標記從第二次出現開始的重複。- 如果需要標記所有重複項,可以使用
keep=False
。
![Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王](https://savingking.com.tw/wp-content/uploads/2025/06/20250609161405_0_de4430.png)
先使用mask = df.duplicated():
![Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王](https://savingking.com.tw/wp-content/uploads/2025/06/20250609162436_0_32920c.png)
推薦hahow線上學習python: https://igrape.net/30afN
近期留言