
在数据处理中,我们经常会遇到需要将汇总数据(例如总销售额、总库存量)按某种比例或规则分配到其组成部分(例如单个销售记录、单个库存单位)的场景。本教程聚焦于一个具体问题:给定两个pandas dataframe,df1包含重复的键(例如产品id),df2包含每个唯一键对应的总数值。我们的目标是创建一个新的dataframe,其结构与df1相似,但df2中的数值已经被“拆分”并按键的出现频率分配到df1的对应行中。
例如,假设我们有以下两个DataFrame:
DataFrame 1 (df1): 包含重复的 id
| id |
|---|
| A |
| B |
| A |
| C |
| A |
| A |
| C |
DataFrame 2 (df2): 包含每个唯一 id 对应的总数值
| id | Col1 | Col2 | Col3 |
|---|---|---|---|
| A | 400 | 100 | 20 |
| B | 200 | 800 | |
| C | 600 | 800 |
期望的输出结果:
| id | Col1 | Col2 | Col3 |
|---|---|---|---|
| A | 100 | 25 | 5 |
| B | 200 | 800 | |
| A | 100 | 25 | 5 |
| C | 300 | 400 | |
| A | 100 | 25 | 5 |
| A | 100 | 25 | 5 |
| C | 300 | 400 |
从期望结果可以看出,id为'A'的记录在df1中出现了4次,因此df2中'A'对应的Col1 (400) 被拆分为 400/4 = 100,Col2 (100) 被拆分为 100/4 = 25,Col3 (20) 被拆分为 20/4 = 5。同样,'C'出现了2次,其数值被拆分为一半。而'B'只出现1次,其数值保持不变。
要实现上述目标,我们需要执行以下几个关键步骤:
我们将使用Pandas库中的value_counts()、div()和merge()函数来高效完成这些操作。
首先,我们创建示例数据:
import pandas as pd
import numpy as np
# 创建 DataFrame 1
data1 = {'id': ['A', 'B', 'A', 'C', 'A', 'A', 'C']}
df1 = pd.DataFrame(data1)
# 创建 DataFrame 2
data2 = {'id': ['A', 'B', 'C'],
'Col1': [400, 200, 600],
'Col2': [100, np.nan, 800],
'Col3': [20, 800, np.nan]}
df2 = pd.DataFrame(data2)
print("原始 df1:")
print(df1)
print("\n原始 df2:")
print(df2)原始 df1:
id 0 A 1 B 2 A 3 C 4 A 5 A 6 C
原始 df2:
id Col1 Col2 Col3 0 A 400 100.0 20.0 1 B 200 NaN 800.0 2 C 600 800.0 NaN
现在,执行核心逻辑:
# 1. 计算 df1 中 'id' 列的频率
id_counts = df1['id'].value_counts()
print("\nid 频率:")
print(id_counts)
# 2. 标准化 df2: 将 df2 中的数值除以对应的 id 频率
# - set_index('id') 将 'id' 设置为索引,以便与 id_counts 对齐
# - div(id_counts, axis=0) 对齐索引并执行逐行除法
df2_standardized = df2.set_index('id').div(id_counts, axis=0)
print("\n标准化后的 df2:")
print(df2_standardized)
# 3. 合并数据
# - df1.reset_index() 暂时将 df1 的原始索引保存为一列,以便后续恢复
# - merge() 根据 'id' 列进行左连接 (how='left')
# - set_index('index').reindex(df1.index) 恢复原始索引和行顺序
out = (df1.reset_index()
.merge(df2_standardized, on='id', how='left')
.set_index('index').reindex(df1.index)
)
print("\n最终输出:")
print(out)id 频率:
A 4 C 2 B 1 Name: id, dtype: int64
标准化后的 df2:
Col1 Col2 Col3 id A 100.0 25.0 5.0 B 200.0 NaN 800.0 C 300.0 400.0 NaN
最终输出:
id Col1 Col2 Col3 0 A 100.0 25.0 5.0 1 B 200.0 NaN 800.0 2 A 100.0 25.0 5.0 3 C 300.0 400.0 NaN 4 A 100.0 25.0 5.0 5 A 100.0 25.0 5.0 6 C 300.0 400.0 NaN
id_counts = df1['id'].value_counts():
df2_standardized = df2.set_index('id').div(id_counts, axis=0):
out = (df1.reset_index().merge(df2_standardized, on='id', how='left').set_index('index').reindex(df1.index)):
本教程提供了一种高效且易于理解的Pandas解决方案,用于根据键的出现频率将一个DataFrame的数值拆分并分配到另一个DataFrame的对应行中。通过结合value_counts()计算频率、div()进行标准化以及merge()进行数据整合,我们能够精确地实现复杂的数值分配逻辑。掌握这种模式对于处理涉及数据聚合、拆分和重构的场景非常有用。
以上就是Pandas DataFrame中基于键匹配与频率拆分数值的教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号