如何用Pandas计算同品牌同行业组内所有数据对的价格销量变化率?
组内全量数据对的「距离」计算实现方案
问题说明
给定数据集包含字段:Brand(品牌)、Sector(行业)、Year(年份)、Price(价格)、Sales(销量),示例数据如下:
| Brand | Sector | Year | Price | Sales |
|---|---|---|---|---|
| B1 | S1 | 2023 | 45900 | 400 |
| B1 | S1 | 2022 | 45000 | 500 |
| B2 | S1 | 2022 | 45400 | 520 |
分组规则:相同Brand + 相同Sector为一个组,需要计算组内所有两两数据对的「距离」,公式为:(A.Price - B.Price)/(A.Sales - B.Sales)
之前用df.diff()、df.roll()只能处理相邻元素,无法生成全量数据对,以下是可行实现方案。
实现步骤(Python Pandas)
1. 构造示例数据
先把给定数据转换成Pandas DataFrame:
import pandas as pd data = [ ["B1", "S1", 2023, 45900, 400], ["B1", "S1", 2022, 45000, 500], ["B2", "S1", 2022, 45400, 520] ] df = pd.DataFrame(data, columns=["Brand", "Sector", "Year", "Price", "Sales"])
2. 定义分组内计算函数
利用itertools.combinations生成组内所有两两数据对,然后逐个计算距离:
from itertools import combinations def calc_group_distance(group): # 生成组内所有行的索引组合(两两配对) pairs = combinations(group.index, 2) results = [] for idx1, idx2 in pairs: a = group.loc[idx1] b = group.loc[idx2] # 计算距离,避免除数为0的情况 if a["Sales"] != b["Sales"]: distance = (a["Price"] - b["Price"]) / (a["Sales"] - b["Sales"]) else: distance = None # 可根据需求修改除数为0的处理逻辑 results.append({ "Brand": a["Brand"], "Sector": a["Sector"], "Year_A": a["Year"], "Year_B": b["Year"], "Price_A": a["Price"], "Price_B": b["Price"], "Sales_A": a["Sales"], "Sales_B": b["Sales"], "Distance": distance }) return pd.DataFrame(results)
3. 分组应用并合并结果
按Brand和Sector分组后,对每个组应用上述函数,最后合并所有结果:
# 分组并计算 result_df = df.groupby(["Brand", "Sector"]).apply(calc_group_distance).reset_index(drop=True) # 查看结果 print(result_df)
输出结果
运行后会得到如下结果(对应B1-S1组的唯一数据对):
| Brand | Sector | Year_A | Year_B | Price_A | Price_B | Sales_A | Sales_B | Distance |
|---|---|---|---|---|---|---|---|---|
| B1 | S1 | 2023 | 2022 | 45900 | 45000 | 400 | 500 | -9.0 |
B2-S1组只有1条数据,没有可配对的元素,因此无输出。
注意事项
- 代码中加入了除数为0的判断,如果组内存在Sales相同的数据对,会返回
None,可根据实际需求修改处理逻辑(比如抛出提示、赋值为特定值等) - 如果数据集较大,可考虑优化性能(比如用向量化操作替代循环,但小规模数据下循环足够简洁直观)
内容的提问来源于stack exchange,提问作者user2458922
相关产品推荐
相关产品推荐

