Pandas数据框列表列处理:根据多条件关联与聚合获取最小值

DDD
发布: 2025-09-26 14:19:01
原创
687人浏览过

Pandas数据框列表列处理:根据多条件关联与聚合获取最小值

本文将介绍如何在Pandas中处理两个数据框的复杂关联场景。当一个数据框的列包含列表型数据(如商店ID列表),而另一个数据框包含具体条目时,我们面临根据月份匹配和商店ID列表包含关系进行数据聚合的需求。教程将详细演示如何利用explode和merge等Pandas高级功能,高效地从源数据框中提取并计算符合条件的最小值,最终实现数据框的精确合并与转换。

场景描述与挑战

在数据分析实践中,我们经常需要从一个数据源(例如,详细的交易记录)中提取信息,并将其关联到另一个数据源(例如,汇总的查询条件)。本教程将解决一个特定但常见的挑战:我们有两个pandas数据框df1和df2。

df1包含具体的商店、对应的数值(value)和月份信息: | store | value | month | | :---- | :---- | :---- | | 1 | 24 | 1 | | 1 | 28 | 2 | | 2 | 29 | 1 | | 2 | 0 | 2 |

df2包含一个商店ID列表(store)和月份信息: | store | month | | :-------- | :---- | | [1, 2, 3] | 1 | | [2] | 2 |

我们的目标是根据以下两个条件,将df1中的value列的最小值添加到df2中:

  1. df1的month必须与df2的month匹配。
  2. df1的store必须包含在df2的store列表之中。
  3. 如果一个df2行对应的商店列表中有多个商店满足条件,我们需要取这些商店对应的value的最小值。

传统的merge操作无法直接处理df2中store列的列表结构,这是实现此目标的主要障碍。

核心思路与Pandas工具

为了解决列表列的关联问题,我们将采用以下核心策略和Pandas功能:

  1. 预聚合df1: 在进行关联之前,先对df1按照store和month进行分组,并计算每个分组的value最小值。这样做可以简化后续的合并操作,并直接获取我们需要的最小值。
  2. 展开df2的列表列: 使用explode()函数将df2中store列的列表展开,使每个列表元素成为独立的一行。这样,df2的store列就不再是列表,而是单个商店ID,从而可以进行标准的合并操作。
  3. 合并数据框: 将展开后的df2与预聚合的df1进行合并,匹配store和month列。
  4. 重新聚合回原始粒度: 由于explode()操作增加了行数,我们需要再次对合并后的结果进行分组,以恢复到df2的原始行粒度,并为每个原始行找到最终的最小值。
  5. 添加结果列: 使用assign()方法将计算出的最小值作为新列添加到df2中。

代码实现步骤

首先,我们创建示例数据框:

import pandas as pd

# 数据框 df1
data1 = {'store': [1, 1, 2, 2], 'value': [24, 28, 29, 0], 'month': [1, 2, 1, 2]}
df1 = pd.DataFrame(data1)
print("df1:")
print(df1)
# df1:
#    store  value  month
# 0      1     24      1
# 1      1     28      2
# 2      2     29      1
# 3      2      0      2

# 数据框 df2
data2 = {'store': [[1, 2, 3], [2]], 'month': [1, 2]}
df2 = pd.DataFrame(data2)
print("\ndf2:")
print(df2)
# df2:
#        store  month
# 0  [1, 2, 3]      1
# 1        [2]      2
登录后复制

接下来,我们按照上述核心思路逐步实现:

步骤一:预处理源数据框 (df1)

为了确保我们获取的是每个商店在特定月份的最小值,我们先对df1进行分组聚合。

# 对df1按'store'和'month'分组,并计算'value'的最小值
df1_min_values = df1.groupby(['store', 'month'], as_index=False)['value'].min()
print("\ndf1_min_values (预聚合后的df1):")
print(df1_min_values)
# df1_min_values (预聚合后的df1):
#    store  month  value
# 0      1      1     24
# 1      1      2     28
# 2      2      1     29
# 3      2      2      0
登录后复制

as_index=False确保store和month作为列而不是索引,方便后续合并。

步骤二:展开目标数据框 (df2) 的列表列

使用explode()函数展开df2中的store列表。由于explode会改变索引,我们使用reset_index()来保存原始行索引,以便后续聚合。

序列猴子开放平台
序列猴子开放平台

具有长序列、多模态、单模型、大数据等特点的超大规模语言模型

序列猴子开放平台 0
查看详情 序列猴子开放平台
# 展开df2的'store'列,并保留原始索引
df2_exploded = df2.explode('store').reset_index()
print("\ndf2_exploded (展开后的df2):")
print(df2_exploded)
# df2_exploded (展开后的df2):
#    index store  month
# 0      0     1      1
# 1      0     2      1
# 2      0     3      1
# 3      1     2      2
登录后复制

这里的index列记录了原始df2的行号,这对于后续将结果聚合回原始df2的粒度至关重要。

步骤三:关联与合并

将展开后的df2_exploded与预聚合的df1_min_values进行左连接(how='left'),基于store和month列进行匹配。

# 合并展开后的df2与预聚合的df1
merged_df = df2_exploded.merge(df1_min_values, on=['store', 'month'], how='left')
print("\nmerged_df (合并后的数据框):")
print(merged_df)
# merged_df (合并后的数据框):
#    index store  month  value
# 0      0     1      1   24.0
# 1      0     2      1   29.0
# 2      0     3      1    NaN
# 3      1     2      2    0.0
登录后复制

注意,df2中store为3的行在df1中没有匹配,因此value显示为NaN。

步骤四:聚合回原始粒度

现在,我们需要根据df2的原始行索引(index列)对merged_df进行分组,并计算每个原始行的value最小值。

# 根据原始索引聚合,获取每个原始行的最小值
final_values = merged_df.groupby('index')['value'].min()
print("\nfinal_values (最终计算出的值):")
print(final_values)
# final_values (最终计算出的值):
# index
# 0    24.0
# 1     0.0
# Name: value, dtype: float64
登录后复制

对于原始df2的第0行 ([1, 2, 3], month=1),合并后得到了24.0、29.0和NaN,其最小值为24.0。 对于原始df2的第1行 ([2], month=2),合并后得到了0.0,其最小值为0.0。

步骤五:整合结果

最后,使用assign()方法将计算出的final_values添加到原始的df2中,形成最终结果。

# 将结果添加到原始df2中
df2_final = df2.assign(value=final_values)
print("\ndf2_final (最终结果数据框):")
print(df2_final)
# df2_final (最终结果数据框):
#        store  month  value
# 0  [1, 2, 3]      1   24.0
# 1        [2]      2    0.0
登录后复制

完整示例代码

import pandas as pd

# 1. 数据准备
data1 = {'store': [1, 1, 2, 2], 'value': [24, 28, 29, 0], 'month': [1, 2, 1, 2]}
df1 = pd.DataFrame(data1)

data2 = {'store': [[1, 2, 3], [2]], 'month': [1, 2]}
df2 = pd.DataFrame(data2)

print("原始df1:")
print(df1)
print("\n原始df2:")
print(df2)

# 2. 核心处理逻辑
# 步骤一:预处理源数据框df1,获取每个store和month组合的value最小值
df1_min_values = df1.groupby(['store', 'month'], as_index=False)['value'].min()

# 步骤二:展开目标数据框df2的列表列,并保存原始索引
df2_exploded = df2.explode('store').reset_index()

# 步骤三:将展开后的df2与预处理的df1进行左连接
merged_df = df2_exploded.merge(df1_min_values, on=['store', 'month'], how='left')

# 步骤四:根据原始索引聚合,获取每个原始df2行的value最小值
# 如果存在NaN,min()函数会忽略NaN,除非所有值都是NaN。
final_values = merged_df.groupby('index')['value'].min()

# 步骤五:将结果添加到原始df2中
df2_result = df2.assign(value=final_values)

print("\n最终结果df2:")
print(df2_result)
登录后复制

注意事项

  1. 性能考虑: explode()操作会显著增加数据框的行数。如果df2的列表列包含大量元素,且df2本身行数很多,这可能会导致内存消耗增加和计算时间延长。对于极大数据集,可能需要考虑其他优化策略,例如使用apply配合列表推导式,但通常explode在性能上优于纯Python循环。
  2. NaN值的处理: 在合并过程中,如果df2_exploded中的某个store或month组合在df1_min_values中没有匹配项,那么value列将填充为NaN。min()函数在计算时会默认忽略NaN值。如果希望NaN参与计算(例如,将其视为0),则需要在聚合前进行填充(fillna(0))。
  3. 索引管理: explode()会重置索引。通过reset_index()创建的index列是追踪原始行归属的关键。理解并正确使用这个索引对于将结果聚合回原始数据框至关重要。
  4. 数据类型: 最终的value列可能会因为NaN值的引入而变为浮点型(float)。如果需要整数类型,且确定没有NaN或已处理NaN,可以使用astype(int)进行类型转换。

总结

本教程详细介绍了如何在Pandas中处理涉及列表型列的复杂数据框关联与聚合问题。通过巧妙地结合explode()、groupby()和merge()等Pandas核心功能,我们能够有效地将列表展开、进行多条件匹配,并最终聚合出所需的结果。这种方法不仅解决了列表列的直接合并难题,也为处理更复杂的数据转换任务提供了强大的工具和清晰的思路。掌握这些技巧,将极大地提升你在Pandas中处理复杂数据结构的能力。

以上就是Pandas数据框列表列处理:根据多条件关联与聚合获取最小值的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号