Pandas 重複值處理

重複的資料可能會影響分析結果,Pandas 提供了檢測和處理重複值的方法。

範例資料

import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Alice', 'Charlie', 'Bob'],
    'age': [25, 30, 25, 35, 30],
    'city': ['Taipei', 'Tokyo', 'Taipei', 'Seoul', 'Tokyo']
})
print(df)
      name  age    city
0    Alice   25  Taipei
1      Bob   30   Tokyo
2    Alice   25  Taipei
3  Charlie   35   Seoul
4      Bob   30   Tokyo

第 0 和 2 列、第 1 和 4 列是重複的。

檢測重複值

duplicated()

回傳布林 Series,標記哪些列是重複的:

print(df.duplicated())
0    False
1    False
2     True
3    False
4     True
dtype: bool

預設會標記第二次出現(及之後)的列為重複。

保留不同的重複項

# 保留第一個,標記後面的為重複(預設)
df.duplicated(keep='first')

# 保留最後一個,標記前面的為重複
df.duplicated(keep='last')

# 所有重複的都標記為 True
df.duplicated(keep=False)

檢查特定欄位

# 只檢查 name 欄是否重複
print(df.duplicated(subset=['name']))

# 檢查多個欄位
print(df.duplicated(subset=['name', 'age']))

找出重複的列

# 取得所有重複的列(包含第一次出現的)
duplicates = df[df.duplicated(keep=False)]
print(duplicates)
    name  age    city
0  Alice   25  Taipei
1    Bob   30   Tokyo
2  Alice   25  Taipei
4    Bob   30   Tokyo

統計重複數量

# 有多少列是重複的
print(df.duplicated().sum())  # 2

# 不重複的列數
print(df.drop_duplicates().shape[0])  # 3

刪除重複值

drop_duplicates()

# 刪除重複列,保留第一個(預設)
df_unique = df.drop_duplicates()
print(df_unique)
      name  age    city
0    Alice   25  Taipei
1      Bob   30   Tokyo
3  Charlie   35   Seoul

保留不同的項目

# 保留最後一個
df_unique = df.drop_duplicates(keep='last')

# 全部刪除(不保留任何重複項)
df_unique = df.drop_duplicates(keep=False)

只根據特定欄位去重

# 只根據 name 欄去重
df_unique = df.drop_duplicates(subset=['name'])
print(df_unique)
      name  age    city
0    Alice   25  Taipei
1      Bob   30   Tokyo
3  Charlie   35   Seoul

去重後重設索引

df_unique = df.drop_duplicates().reset_index(drop=True)

計算各值出現次數

# name 欄各值出現的次數
print(df['name'].value_counts())
Alice      2
Bob        2
Charlie    1
Name: name, dtype: int64
# 找出出現超過 1 次的值
counts = df['name'].value_counts()
duplicated_names = counts[counts > 1].index.tolist()
print(duplicated_names)  # ['Alice', 'Bob']

實際應用範例

找出重複的 email

df = pd.DataFrame({
    'user_id': [1, 2, 3, 4, 5],
    'email': ['a@test.com', 'b@test.com', 'a@test.com', 'c@test.com', 'b@test.com']
})

# 找出重複的 email
dup_emails = df[df.duplicated(subset=['email'], keep=False)]
print(dup_emails)

保留最新的一筆

df = pd.DataFrame({
    'user_id': [1, 1, 2, 2],
    'date': ['2024-01-01', '2024-01-15', '2024-01-10', '2024-01-20'],
    'value': [100, 150, 200, 180]
})
df['date'] = pd.to_datetime(df['date'])

# 先按日期排序,再保留每個 user_id 的最後一筆
df_latest = df.sort_values('date').drop_duplicates(subset=['user_id'], keep='last')
print(df_latest)

合併重複資料

如果重複的資料需要合併(例如加總)而不是刪除:

df = pd.DataFrame({
    'product': ['A', 'B', 'A', 'B', 'A'],
    'sales': [100, 200, 150, 180, 120]
})

# 用 groupby 合併
df_merged = df.groupby('product')['sales'].sum().reset_index()
print(df_merged)
  product  sales
0       A    370
1       B    380