You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于双因子使用Python将全国营收拆分至各城市的实现方法

全国啤酒营收按城市拆分的算法方案与Python实现

算法思路

你提出的线性拆分模型属于 带总量等式约束的双因子加权分配问题,核心是求解符合业务逻辑的权重系数,具体逻辑如下:

  • 问题核心约束:所有城市计算得到的啤酒营收之和严格等于全国总营收,且两个因子的权重不能为负(消费支出越高、人均GDP越高的城市,啤酒营收理论上越高,负权重不符合消费常识)。
  • 权重确定规则:如果没有城市级啤酒营收的抽样真值,可通过业务认知先确定两个因子的相对贡献占比(比如大众快消品的营收和城市总消费支出相关性更高,可给消费支出设70%权重,人均GDP设30%权重;无明确业务先验时可默认两个因子各占50%权重),再通过总量约束直接推导权重的解析解,无需复杂迭代优化。
  • 如果有10个以上城市的真实啤酒营收抽样数据,可改用带等式约束的非负最小二乘拟合权重,拟合结果会更贴合实际业务规律。
  • 结果校验:拆分完成后需做合理性校验,排除人口规模、消费能级差异大的城市出现营收倒挂的异常情况。

Python实现

依赖准备

仅需numpy、pandas两个基础数据处理库,如需做带样本的约束拟合,额外安装scipy即可:

pip install pandas numpy scipy

场景1:无城市级真值样本(最通用场景,严格匹配预设线性公式)

该实现严格遵循 city_beer = x * city_consumer_spending + y * city_gdp_per_capita 的公式,计算结果自然满足总和等于全国总营收的约束:

import pandas as pd
import numpy as np

# --------------------------
# 1. 读取数据,替换为真实数据路径
# 数据需包含三列:
# city: 城市名称
# consumer_spending: 城市年度总消费支出(与全国啤酒营收单位保持一致,比如均为百万欧元)
# gdp_per_capita: 城市年度人均GDP(单位与总营收统计口径对齐)
# --------------------------
df = pd.read_csv("germany_city_data.csv")
national_beer_total = 120000  # 替换为德国全国年度啤酒总营收的真实值

# --------------------------
# 2. 设定两个因子的相对贡献占比,可根据业务调整
# 这里默认总消费支出贡献占70%,人均GDP贡献占30%
# --------------------------
spending_contrib = 0.7
gdp_contrib = 1 - spending_contrib

# --------------------------
# 3. 反解线性公式的系数x、y
# 推导逻辑:x/y = (spending_contrib / 消费支出均值) / (gdp_contrib / 人均GDP均值),保证两个因子的贡献占比符合设定
# 再代入约束 x*sum(消费支出) + y*sum(人均GDP) = 全国总营收,得到解析解
# --------------------------
sum_spending = df["consumer_spending"].sum()
sum_gdp = df["gdp_per_capita"].sum()
mean_spending = df["consumer_spending"].mean()
mean_gdp = df["gdp_per_capita"].mean()

# 计算系数比k = x/y
k = (spending_contrib / mean_spending) / (gdp_contrib / mean_gdp)
# 求解x、y
x = national_beer_total / (sum_spending + sum_gdp / k)
y = x / k

# --------------------------
# 4. 计算每个城市的啤酒营收
# --------------------------
df["city_beer_revenue"] = x * df["consumer_spending"] + y * df["gdp_per_capita"]

# 校验:总和是否等于全国总营收(浮点误差范围内可忽略)
print(f"拆分后营收总和:{df['city_beer_revenue'].sum():.2f},全国总营收:{national_beer_total}")

# 导出结果
df.to_csv("germany_city_beer_revenue.csv", index=False)

场景2:有部分城市啤酒营收抽样数据(拟合更精准)

如果有部分城市的真实啤酒营收数据,可通过带约束的最小二乘拟合x、y,约束条件为所有城市预测值总和等于全国总营收、权重非负:

from scipy.optimize import minimize

# 假设有抽样数据的城市存在sample_revenue列,无抽样数据的该列为空
sample_df = df[~df["sample_revenue"].isna()].copy()
X_sample = sample_df[["consumer_spending", "gdp_per_capita"]].values
y_sample = sample_df["sample_revenue"].values

# 定义损失函数:最小化抽样城市的预测误差
def loss(coef):
    x, y = coef
    y_pred = X_sample[:,0]*x + X_sample[:,1]*y
    return np.mean((y_pred - y_sample)**2)

# 定义约束:所有城市预测值总和等于全国总营收
constraints = ({
    'type': 'eq',
    'fun': lambda coef: (df["consumer_spending"]*coef[0] + df["gdp_per_capita"]*coef[1]).sum() - national_beer_total
})
# 定义边界:权重非负
bounds = ((0, None), (0, None))

# 初始化权重、求解
init_coef = [x, y]  # 用场景1的计算结果作为初始值,加快收敛
res = minimize(loss, init_coef, method='SLSQP', bounds=bounds, constraints=constraints)
x_fit, y_fit = res.x

# 计算全量城市的啤酒营收
df["city_beer_revenue_fit"] = x_fit * df["consumer_spending"] + y_fit * df["gdp_per_capita"]

注意事项

  • 所有指标必须统一统计周期、统一货币单位,避免口径不一致导致结果偏差。
  • 因子相对贡献占比可根据业务调整:如果高端啤酒占比较高,可适当提高人均GDP的权重;如果大众平价啤酒占比高,可提高总消费支出的权重。
  • 拆分完成后建议分层校验:按城市人口规模、消费能级分层,检查同层级城市的啤酒营收是否在合理区间,避免出现小城市营收高于同类型大城市的异常。

内容的提问来源于stack exchange,提问作者Ng.Alina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 14:54:19