值得一看
广告
彩虹云商城
广告

热门广告位

Pandas数据帧中高效筛选N个重复项并保留最后N条记录

Pandas数据帧中高效筛选N个重复项并保留最后N条记录

本教程将探讨如何在Pandas数据帧中高效处理重复数据,具体目标是针对指定列的重复组,仅保留每组的最后N条记录。我们将介绍并演示使用groupby().tail()方法的简洁实现,该方法对于在内存中处理中等规模数据集时,能提供比基于行号的窗口函数更直观和高效的解决方案。

问题描述与背景

在数据处理过程中,我们经常会遇到需要从数据集中筛选重复记录的场景。有时,我们并非要完全删除所有重复项,而是希望为每个重复组保留特定数量的记录,例如最新的n条或按某种顺序排列的最后n条记录。

考虑一个包含用户交易记录或日志条目的数据帧,其中first_name、last_name和sex可能存在大量重复,但id和country是唯一的。我们的目标是,对于每个相同的first_name、last_name和sex组合,只保留其对应的最后3条记录(通常根据id或其他时间戳字段来定义“最后”)。

原始数据帧示例如下:

id first_name last_name sex country
01 John Doe Male USA
02 John Doe Male Canada
03 John Doe Male Mexico
04 Mark Kay Male Italy
05 John Doe Male Spain
06 Mark Kay Male France
07 John Doe Male Peru
08 Mark Kay Male India
09 Mark Kay Male Laos
10 John Doe Male Benin

期望结果是,对于John Doe Male和Mark Kay Male这两个重复组,分别只保留其最后3条记录:

id first_name last_name sex country
05 John Doe Male Spain
06 Mark Kay Male France
07 John Doe Male Peru
08 Mark Kay Male India
09 Mark Kay Male Laos
10 John Doe Male Benin

对于大规模数据集,尤其是在分布式计算环境如Spark中,一种常见的解决方案是使用窗口函数(Window.partitionBy().orderBy().row_number())来为每个组内的记录分配行号,然后筛选出小于等于N的记录。这种方法在Spark中是标准且高效的,但在Pandas中,我们有更简洁且同样高效的替代方案。

Pandas groupby().tail() 方法详解

Pandas库提供了一个非常直观且高效的方法groupby().tail(n)来解决上述问题。它允许我们对数据帧进行分组,然后从每个组的末尾选择指定数量的记录。

核心思想

df.groupby(by_columns).tail(n)的工作原理是:

  1. 根据by_columns指定的列将数据帧分成若干个组。
  2. 对于每个独立的分组,从其末尾(即最后)选取n条记录。
  3. 将这些选取的记录合并成一个新的数据帧。

需要注意的是,tail()方法中的“末尾”是基于当前数据帧的行顺序。因此,如果“最后N条”的定义是基于某个特定字段(例如时间戳或ID)的最新记录,那么在应用groupby().tail()之前,对数据帧进行相应的排序是至关重要的一步。

Natural Language Playlist

Natural Language Playlist

探索语言和音乐之间丰富而复杂的关系,并使用 Transformer 语言模型构建播放列表。

Natural Language Playlist35

查看详情
Natural Language Playlist

实现步骤

以下是使用Pandas groupby().tail() 方法的详细实现步骤:

  1. 导入必要的库
    首先,我们需要导入pandas库。

  2. 创建示例数据帧
    为了演示,我们使用与问题描述中相同的数据来构建一个Pandas DataFrame。

  3. 数据排序(关键步骤)
    由于我们希望保留“最后3条”记录,并且这个“最后”是基于id列的递增顺序来定义的,因此在执行分组和选择操作之前,必须先根据id列对整个数据帧进行升序排序。这确保了在每个组内,tail(3)操作会正确地选择具有最大id值的3条记录。

  4. 应用 groupby() 和 tail()
    使用groupby()方法指定分组的键(first_name, last_name, sex),然后链式调用tail(3)来保留每个组的最后3条记录。

  5. 重置索引(可选)
    groupby().tail()操作会保留原始数据帧的索引。如果需要一个从0开始的连续新索引,可以调用reset_index(drop=True)。

示例代码

import pandas as pd
# 1. 创建示例数据帧
data = {
'id': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'first_name': ['John', 'John', 'John', 'Mark', 'John', 'Mark', 'John', 'Mark', 'Mark', 'John'],
'last_name': ['Doe', 'Doe', 'Doe', 'Kay', 'Doe', 'Kay', 'Doe', 'Kay', 'Kay', 'Doe'],
'sex': ['Male', 'Male', 'Male', 'Male', 'Male', 'Male', 'Male', 'Male', 'Male', 'Male'],
'country': ['USA', 'Canada', 'Mexico', 'Italy', 'Spain', 'France', 'Peru', 'India', 'Laos', 'Benin']
}
df = pd.DataFrame(data)
print("原始数据帧:")
print(df)
print("-" * 30)
# 2. 排序数据帧:确保 '最后N条' 是根据 'id' 的最新值
# 如果不排序,tail(3)会根据原始输入顺序的最后3行来取
df_sorted = df.sort_values(by='id', ascending=True)
# 3. 使用 groupby().tail() 保留每个组的最后3条记录
# 分组键为 'first_name', 'last_name', 'sex'
# tail(3) 表示保留每个组的最后3行
result_df = df_sorted.groupby(['first_name', 'last_name', 'sex']).tail(3)
# 4. 重置索引(可选,使索引从0开始连续)
result_df = result_df.reset_index(drop=True)
print("\n筛选后的数据帧 (保留每个重复组的最后3条记录):")
print(result_df)

输出结果

运行上述代码将得到以下输出:

原始数据帧:
id first_name last_name   sex country
0   1       John       Doe  Male     USA
1   2       John       Doe  Male  Canada
2   3       John       Doe  Male  Mexico
3   4       Mark       Kay  Male   Italy
4   5       John       Doe  Male   Spain
5   6       Mark       Kay  Male  France
6   7       John       Doe  Male    Peru
7   8       Mark       Kay  Male   India
8   9       Mark       Kay  Male    Laos
9  10       John       Doe  Male   Benin
------------------------------
筛选后的数据帧 (保留每个重复组的最后3条记录):
id first_name last_name   sex country
0   5       John       Doe  Male   Spain
1   6       Mark       Kay  Male  France
2   7       John       Doe  Male    Peru
3   8       Mark       Kay  Male   India
4   9       Mark       Kay  Kay   Laos
5  10       John       Doe  Male   Benin

方法比较与适用场景

  • Pandas groupby().tail():

    • 优点: 代码简洁,易于理解和实现。对于在内存中能够处理的数据集(通常是中等规模),其执行效率非常高。避免了显式创建额外的行号列,减少了中间步骤。
    • 适用场景: 适用于数据量可以在单机内存中处理的场景,或者作为数据探索和预处理的快速方法。
  • Spark 窗口函数 (row_number()):

    • 优点: 专为分布式计算设计,能够高效处理PB级别的大规模数据集。是Spark中处理此类分组排序筛选问题的标准和推荐方法。
    • 适用场景: 适用于需要处理超出单机内存容量的超大规模数据集,或在Hadoop/Spark集群环境中进行数据处理的场景。

选择建议:
如果您正在使用Pandas处理数据,并且数据集大小适中(能够完全载入内存),那么groupby().tail()无疑是实现此目标的最佳选择,它提供了简洁性和高效性。如果您在分布式环境(如Spark)中工作,并且数据量巨大,那么使用Spark的窗口函数是更合适的策略。

注意事项

  • 排序的重要性: 再次强调,如果“最后N条”的定义依赖于某个特定字段的顺序(例如时间戳、ID等),则在应用groupby().tail()之前,务必对数据帧进行相应的排序。否则,tail()将根据数据帧当前的物理顺序来选取行。
  • 性能考量: 尽管groupby().tail()在Pandas中效率很高,但Pandas本身是基于内存的库。对于数十GB甚至TB级别的数据,即使使用此方法,也可能遇到内存限制。在这种情况下,分布式计算框架(如Spark)是不可避免的选择。
  • head() 与 tail(): 与tail(n)类似,Pandas也提供了groupby().head(n)方法,用于保留每个分组的前N条记录。根据具体需求,可以选择使用head()或tail()。

总结

通过本教程,我们学习了如何在Pandas数据帧中高效地筛选出每个重复组的最后N条记录。df.sort_values().groupby().tail(n).reset_index(drop=True)这一组合操作提供了一个简洁而强大的解决方案,尤其适用于在内存中处理中等规模数据集的场景。理解其背后的原理以及排序的重要性,将帮助您更灵活、更高效地进行数据清洗和预处理工作。在面对不同规模和环境的数据时,选择合适的工具和方法是数据处理成功的关键。

相关标签:

工具 ai win 数据排序 排列 分布式 pandas hadoop spark
温馨提示: 本文最后更新于2025-09-05 16:30:33,某些文章具有时效性,若有错误或已失效,请在下方留言或联系在线客服
文章版权声明 1 本网站名称: 创客网
2 本站永久网址:https://new.ie310.com
1 本文采用非商业性使用-相同方式共享 4.0 国际许可协议[CC BY-NC-SA]进行授权
2 本站所有内容仅供参考,分享出来是为了可以给大家提供新的思路。
3 互联网转载资源会有一些其他联系方式,请大家不要盲目相信,被骗本站概不负责!
4 本网站只做项目揭秘,无法一对一教学指导,每篇文章内都含项目全套的教程讲解,请仔细阅读。
5 本站分享的所有平台仅供展示,本站不对平台真实性负责,站长建议大家自己根据项目关键词自己选择平台。
6 因为文章发布时间和您阅读文章时间存在时间差,所以有些项目红利期可能已经过了,能不能赚钱需要自己判断。
7 本网站仅做资源分享,不做任何收益保障,创业公司上收费几百上千的项目我免费分享出来的,希望大家可以认真学习。
8 本站所有资料均来自互联网公开分享,并不代表本站立场,如不慎侵犯到您的版权利益,请联系79283999@qq.com删除。

本站资料仅供学习交流使用请勿商业运营,严禁从事违法,侵权等任何非法活动,否则后果自负!
THE END
喜欢就支持一下吧
点赞11赞赏 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容