Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = [‘name’] )

加入好友
加入社群
Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王

在使用 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'] ) - 儲蓄保險王

現在,讓我們試試三種看似相同的計數方式:

# 方法 1GroupBy.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'] ) - 儲蓄保險王

為什麼方法 2 的結果是 8 而不是 4?讓我們深入了解背後的原因。

Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王

🔍 核心概念解析

1. size 屬性 vs size() 方法

在 Pandas 中,size 既可以是屬性也可以是方法,取決於使用的物件:

Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王

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'] ) - 儲蓄保險王

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'] ) - 儲蓄保險王

💡 關鍵差異詳解

讓我們回到最初的問題,為什麼遍歷時會得到不同的結果:

情況 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'] ) - 儲蓄保險王

情況 2:SeriesGroupBy(結果為 4)

Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王

📊 實用技巧總結

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'] ) - 儲蓄保險王

常見使用場景

# 場景 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'] ) - 儲蓄保險王

🎯 重點整理

  1. DataFrame/Seriessize屬性(不用括號),返回總元素數
  2. GroupBysize()方法(要用括號),返回每組行數
  3. 遍歷 DataFrameGroupBy 得到的是 DataFrame,其 size = 行數 × 列數
  4. 遍歷 SeriesGroupBy 得到的是 Series,其 size = 元素個數
  5. 計算分組數量時,優先使用 GroupBy.size() 方法或 value_counts()
  6. 若確定資料為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'] ) - 儲蓄保險王

使用 .duplicated()

Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王

解釋:

  • 第 0 行(Alice)是第一次出現,因此標記為 False
  • 第 1 行(Bob)是第一次出現,因此標記為 False
  • 第 2 行(Alice)是重複項,因此標記為 True
  • 第 3 行(Charlie)是第一次出現,因此標記為 False
  • 第 4 行(Bob)是重複項,因此標記為 True
  • 第 5 行(Alice)是重複項,因此標記為 True

為什麼「少一次」?

因為 .duplicated() 的邏輯是:

  1. 第一次出現的項目被認為是唯一的,標記為 False
  2. 只有從第二次開始出現的項目,才會被標記為 True

因此,當你只看 .duplicated() 的結果時,重複的項目中確實會「少一次」,即第一次出現的項目不會算入重複。


如果需要標記所有重複項

如果你希望包括第一次出現的項目也標記為重複,可以使用以下方法:

Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王

解釋:

  • keep=False 表示所有重複項,包括第一次出現的項目,都會被標記為 True

總結

  • .duplicated() 默認只標記從第二次出現開始的重複。
  • 如果需要標記所有重複項,可以使用 keep=False
Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王

先使用mask = df.duplicated():

Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王

推薦hahow線上學習python: https://igrape.net/30afN

加入好友
加入社群
Python Pandas GroupBy 的 size 陷阱:為什麼你的計數結果總是不對?如何計算重複次數? duplicates = df.duplicated( subset = ['name'] ) - 儲蓄保險王

儲蓄保險王

儲蓄險是板主最喜愛的儲蓄工具,最喜愛的投資理財工具則是ETF,最喜愛的省錢工具則是信用卡

You may also like...

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *