使用Pandas和NumPy高效计算首个唯一值分组汇总

使用pandas和numpy高效计算首个唯一值分组汇总

本教程详细讲解如何利用Pandas和NumPy在数据集中创建一个新的“累计销售额”列。该列仅在每个唯一客户ID的首次出现时显示其总销售额,而在该客户ID的后续出现时则显示为零。文章将通过实际代码示例,深入解析`numpy.where`、`Series.duplicated`和`GroupBy.transform`的组合应用,提供一种高效且地道的解决方案。

在数据分析中,我们经常需要根据特定条件对数据进行汇总或标记。一个常见的场景是,我们希望在一个分组数据集中,仅在每个分组的第一个实例处显示该分组的总计值,而其余实例则显示为零。例如,在一个客户销售记录中,我们可能需要一个“累计销售额”列,它只在客户首次出现时显示该客户的总销售额,而在该客户的后续交易记录中则显示为零。

场景描述与数据示例

假设我们有一个包含客户ID、日期和单次销售额的数据集,我们希望创建一个名为Cumulative Sales的新列,其逻辑如下:

对于每个唯一的ClientID,仅在其首次出现的那一行计算并显示该客户所有Total sales的总和。对于同一个ClientID的后续出现,Cumulative Sales列的值应为0。

以下是我们的初始数据集示例:

import pandas as pdimport numpy as npdata = {    'ClientID': ['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C', 'D', 'D'],    'Date': ['01-01-2000', '01-02-2000', '01-03-2000', '01-01-2000', '01-02-2000',             '01-01-2000', '01-02-2000', '01-03-2000', '01-01-2000', '01-02-2000'],    'Total sales': [100, 100, 100, 50, 50, 70, 70, 70, 20, 20]}df = pd.DataFrame(data)print("原始数据框:")print(df)

原始数据框输出如下:

原始数据框:  ClientID        Date  Total sales0        A  01-01-2000          1001        A  01-02-2000          1002        A  01-03-2000          1003        B  01-01-2000           504        B  01-02-2000           505        C  01-01-2000           706        C  01-02-2000           707        C  01-03-2000           708        D  01-01-2000           209        D  01-02-2000           20

我们的目标是生成一个Cumulative Sales列,使其看起来像这样:

  ClientID        Date  Total sales  Cumulative Sales0        A  01-01-2000          100               3001        A  01-02-2000          100                 02        A  01-03-2000          100                 03        B  01-01-2000           50               1004        B  01-02-2000           50                 05        C  01-01-2000           70               2106        C  01-02-2000           70                 07        C  01-03-2000           70                 08        D  01-01-2000           20                409        D  01-02-2000           20                 0

解决方案:结合Pandas duplicated 和 groupby().transform 与 NumPy where

为了实现上述逻辑,我们可以利用Pandas的Series.duplicated()方法来识别重复值,结合DataFrameGroupBy.transform()来计算分组总和,并最终使用NumPy的numpy.where()函数进行条件赋值。

1. 识别重复的客户ID

df[‘ClientID’].duplicated()方法会返回一个布尔型Series,其中True表示该元素是其在Series中首次出现后的重复项,False则表示该元素是首次出现。

print(df['ClientID'].duplicated())# 输出:# 0    False# 1     True# 2     True# 3    False# 4     True# 5    False# 6     True# 7     True# 8    False# 9     True# Name: ClientID, dtype: bool

这个布尔Series正是我们需要的掩码:False对应的是每个ClientID的首次出现,True对应的是后续出现。

2. 计算每个客户的总销售额并广播

df.groupby(‘ClientID’)[‘Total sales’].transform(‘sum’)会执行以下操作:

算家云 算家云

高效、便捷的人工智能算力服务平台

算家云 37 查看详情 算家云 df.groupby(‘ClientID’): 按ClientID列进行分组。[‘Total sales’]: 选取Total sales列进行操作。.transform(‘sum’): 对每个分组内的Total sales求和,并将结果“广播”回原始DataFrame的形状。这意味着,对于属于同一个ClientID的所有行,它们在transform操作后的结果列中将拥有相同的总和值。

print(df.groupby('ClientID')['Total sales'].transform('sum'))# 输出:# 0    300# 1    300# 2    300# 3    100# 4    100# 5    210# 6    210# 7    210# 8     40# 9     40# Name: Total sales, dtype: int64

这个Series包含了每个客户的总销售额,并将其正确地对齐到原始DataFrame的索引。

3. 条件赋值:使用 numpy.where

numpy.where(condition, x, y)函数根据条件选择值:

如果condition为True,则选择x。如果condition为False,则选择y。

结合我们之前得到的两个结果:

condition: df[‘ClientID’].duplicated() (当客户ID是重复时为True,首次出现时为False)x (当条件为True时选择的值): 0 (因为我们希望重复的客户ID显示0)y (当条件为False时选择的值): df.groupby(‘ClientID’)[‘Total sales’].transform(‘sum’) (因为我们希望首次出现的客户ID显示其总销售额)

因此,完整的解决方案代码如下:

df['Cumulative Sales'] = np.where(df['ClientID'].duplicated(),                                  0,                                  df.groupby('ClientID')['Total sales'].transform('sum'))print("n处理后的数据框:")print(df)

输出结果:

处理后的数据框:  ClientID        Date  Total sales  Cumulative Sales0        A  01-01-2000          100               3001        A  01-02-2000          100                 02        A  01-03-2000          100                 03        B  01-01-2000           50               1004        B  01-02-2000           50                 05        C  01-01-2000           70               2106        C  01-02-2000           70                 07        C  01-03-2000           70                 08        D  01-01-2000           20                409        D  01-02-2000           20                 0

这完美地实现了我们的目标。

总结与注意事项

这种方法利用了Pandas和NumPy的矢量化操作,效率非常高,尤其适用于大型数据集。

Series.duplicated(): 默认情况下,它会将第一次出现的值标记为False,其余重复值标记为True。如果需要将最后一次出现的值标记为False,可以使用keep=’last’参数。GroupBy.transform(): 这是一个非常强大的方法,它允许你在分组后执行聚合操作,并将结果返回到与原始DataFrame相同索引和形状的Series或DataFrame中,这使得它非常适合与assign或直接赋值结合使用。numpy.where(): 提供了一种简洁高效的条件赋值方式,避免了使用循环,显著提升了性能。

通过掌握这种组合技巧,你可以在处理复杂的数据转换任务时,以更简洁、更高效的方式实现目标。

以上就是使用Pandas和NumPy高效计算首个唯一值分组汇总的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/571732.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月10日 06:20:22
下一篇 2025年11月10日 06:21:44

相关推荐

发表回复

登录后才能评论
关注微信