趋近智
理解重复数据的存在及其问题至关重要,这对于有效的数据预处理是必不可少的。一个实际操作的例子演示了如何使用Python和广受欢迎的pandas库来查找和删除示例数据集中的重复条目。这项实践是准备数据以进行可靠分析或模型训练的一个标准步骤。
首先,假设我们已经将数据加载到pandas DataFrame中。我们来创建一个表示客户订单的小型示例DataFrame,以说明这些原理:
import pandas as pd
# 包含重复数据的示例数据
data = {
'order_id': [1, 2, 3, 1, 4, 5, 6, 7],
'customer_id': [10, 20, 10, 10, 30, 20, 10, 40],
'item': ['Apple', 'Banana', 'Orange', 'Apple', 'Apple', 'Banana', 'Apple', 'Grape'],
'quantity': [5, 10, 3, 5, 2, 10, 5, 20],
'status': ['Shipped', 'Pending', 'Shipped', 'Shipped', 'Delivered', 'Cancelled', 'Shipped', 'Pending']
}
orders_df = pd.DataFrame(data)
print("原始DataFrame:")
print(orders_df)
运行这段代码将显示我们的初始数据集:
Original DataFrame:
order_id customer_id item quantity status
0 1 10 Apple 5 Shipped # 原始数据
1 2 20 Banana 10 Pending
2 3 10 Orange 3 Shipped
3 1 10 Apple 5 Shipped # 第0行的重复项
4 4 30 Apple 2 Delivered
5 5 20 Banana 10 Cancelled # 与第1行具有相同客户ID/商品
6 6 10 Apple 5 Shipped # 第0行的重复项
7 7 40 Grape 20 Pending
请注意,第0、3和6行在所有列上看起来都相同。第5行与第1行具有相同的customer_id和item,但status不同。
为了找到与前面行完全相同的行,pandas提供了duplicated()方法。它返回一个布尔Series,其中True表示该行是前面某行的重复项。
# 识别完全重复项
duplicate_rows = orders_df.duplicated()
print("\n重复行的布尔掩码:")
print(duplicate_rows)
Output:
Boolean mask for duplicate rows:
0 False
1 False
2 False
3 True # 这一行与第0行相同
4 False
5 False
6 True # 这一行与第0行相同
7 False
dtype: bool
默认情况下,duplicated()会将除了第一次出现之外的所有重复项标记为重复。我们可以使用这个布尔Series来筛选DataFrame,只查看重复的行:
# 显示实际的重复行
print("\n完全重复的行:")
print(orders_df[duplicate_rows])
Output:
Complete duplicate rows:
order_id customer_id item quantity status
3 1 10 Apple 5 Shipped
6 6 10 Apple 5 Shipped
这证实了索引为3和6的行确实是前面某行(本例中为第0行)的完全重复项。
有时,我们根据列的一个子集来定义重复。例如,如果customer_id和item相同,无论order_id或status如何,订单都可能被视为重复。我们可以使用subset参数来检查这一点。
# 基于'customer_id'和'item'识别重复项
partial_duplicates = orders_df.duplicated(subset=['customer_id', 'item'])
print("\n部分重复项的布尔掩码(customer_id, item):")
print(partial_duplicates)
# 显示基于子集被视为重复的行
print("\n基于'customer_id'和'item'被视为重复的行:")
print(orders_df[partial_duplicates])
Output:
Boolean mask for partial duplicates (customer_id, item):
0 False
1 False
2 False
3 True # 与第0行具有相同的 customer_id=10, item='Apple'
4 False
5 True # 与第1行具有相同的 customer_id=20, item='Banana'
6 True # 与第0行具有相同的 customer_id=10, item='Apple'
7 False
dtype: bool
Rows considered duplicates based on 'customer_id' and 'item':
order_id customer_id item quantity status
3 1 10 Apple 5 Shipped
5 5 20 Banana 10 Cancelled
6 6 10 Apple 5 Shipped
在这里,第3和第6行被标记,因为它们重复了第0行中的(10, 'Apple')组合。第5行被标记,因为它重复了第1行中的(20, 'Banana')组合。
一旦识别出重复项,使用drop_duplicates()方法删除它们就非常简单了。
要删除所有列都相同的行,我们调用不带任何参数的drop_duplicates()。默认情况下,它会保留第一次出现,并删除后续的重复项。
# 删除完全重复的行,保留第一次出现
orders_df_no_full_duplicates = orders_df.drop_duplicates()
print("\n删除完全重复项后的DataFrame(保留第一次出现):")
print(orders_df_no_full_duplicates)
Output:
DataFrame after removing complete duplicates (keeping first):
order_id customer_id item quantity status
0 1 10 Apple 5 Shipped
1 2 20 Banana 10 Pending
2 3 10 Orange 3 Shipped
4 4 30 Apple 2 Delivered
5 5 20 Banana 10 Cancelled
7 7 40 Grape 20 Pending
第3和第6行已被删除。
您可以使用keep参数来更改保留哪一行:
keep='first'(默认):保留第一次出现,删除其他。keep='last':保留最后一次出现,删除较早的。keep=False:删除所有有重复的行。使用keep='last'的例子:
# 删除完全重复项,保留最后一次出现
orders_df_keep_last = orders_df.drop_duplicates(keep='last')
print("\n删除完全重复项后的DataFrame(保留最后一次出现):")
print(orders_df_keep_last)
Output:
DataFrame after removing complete duplicates (keeping last):
order_id customer_id item quantity status
1 2 20 Banana 10 Pending
2 3 10 Orange 3 Shipped
4 4 30 Apple 2 Delivered
5 5 20 Banana 10 Cancelled
6 6 10 Apple 5 Shipped # 保留了(10, 'Apple')的最后一次重复
7 7 40 Grape 20 Pending
现在,第6行被保留,而不是第0行,而第0和第3行被删除。
我们也可以将subset和keep与drop_duplicates一起使用。我们来删除customer_id和item重复的行,只保留每种组合的第一个实例。
# 基于'customer_id'和'item'删除重复项,保留第一次出现
orders_df_no_partial_duplicates = orders_df.drop_duplicates(subset=['customer_id', 'item'], keep='first')
print("\n删除部分重复项后的DataFrame(customer_id, item - 保留第一次出现):")
print(orders_df_no_partial_duplicates)
Output:
DataFrame after removing partial duplicates (customer_id, item - keeping first):
order_id customer_id item quantity status
0 1 10 Apple 5 Shipped # 第一个(10, Apple)
1 2 20 Banana 10 Pending # 第一个(20, Banana)
2 3 10 Orange 3 Shipped
4 4 30 Apple 2 Delivered
7 7 40 Grape 20 Pending
第3、5和6行被删除,因为它们的(customer_id, item)对((10, 'Apple')和(20, 'Banana'))已经出现过。
删除重复项后,验证结果是一个好的习惯。您可以检查新DataFrame的维度,或者重新运行duplicated().sum()检查。
# 验证orders_df_no_full_duplicates中没有剩余的完全重复项
remaining_duplicates = orders_df_no_full_duplicates.duplicated().sum()
print(f"\n剩余完全重复项的数量:{remaining_duplicates}")
# 验证orders_df_no_partial_duplicates中没有剩余的部分重复项
remaining_partial = orders_df_no_partial_duplicates.duplicated(subset=['customer_id', 'item']).sum()
print(f"剩余部分重复项的数量(customer_id, item):{remaining_partial}")
Output:
Number of remaining complete duplicates: 0
Number of remaining partial duplicates (customer_id, item): 0
这证实了相应的drop_duplicates操作按预期工作。
本次实际练习说明了如何使用标准工具有效识别和管理重复数据。是检查完全重复项还是使用子集进行检查,完全取决于您的数据背景和分析目标。删除重复项可以确保每条记录都适当地用于您的发现,并防止计数虚高或模型结果出现偏差。
这部分内容有帮助吗?
subset和keep参数的使用说明。© 2026 ApX Machine Learning用心打造