
文章目录
-
- 1. 结论先行
- 2. 环境信息
- 3. 数据与口径:三个涨跌幅、两种单位、一个基准
- 4. 核心代码
- 5. 运行结果:八项里六项在跌
- 6. 可视化:跌幅排行与菜心的季节脾气
- 7. 批发跌、体感贵:缺口去哪了
- 8. 踩坑与避坑
- 9. 总结
- 参考链接
1. 结论先行
“现在买菜越来越贵”——用政府统计处官方批发价数据(8 项主要食品 × 42 个月,2023-01 至 2026-06)算了一遍,结论出乎意料:菜篮子整体跌了 10.4%(等权指数 100 → 89.6)。白白菜批发价 -33.6%、活猪 -29.4%、菜心 -16.3%;8 项里只有金线鱼和番茄微涨 2%。
你的体感也没错——你买的是零售价,这篇算的是批发价,中间隔着运输、租金、人工和零售加成。两个数字都对,背离本身就是最有信息量的部分:批发端三年通缩,零售端体感坚挺,缺口被谁吃掉了,值得每个看物价新闻的人想一层。
2. 环境信息
- Python 3.13,只用标准库(urllib / json)+ matplotlib,零第三方依赖
- 数据源:C&SD 官方 JSON API censtatd.gov.hk/api/get.php?id=990-92077&lang=en&full_series=1(Table 990-92077:8 项主要食品平均批发价,月度,2023-01 至 2026-06 共 42 个月)
- 单位注意:活牛/活猪按每吨计(8-8.7 万港元/吨),蔬菜和鱼按每公斤计(6-11 港元/公斤)——混算前必须分组
- 诚实边界:批发价不等于零售价;8 个食品项是"主要食品"口径,不代表全部食材
3. 数据与口径:三个涨跌幅、两种单位、一个基准
42 个月 × 8 项,每条序列做同一个对照:2023 年全年均值 vs 2026 年上半年均值(1-6 月),涨幅 = 后者/前者 – 1。选这两年做基准端点有两个理由:2023 是序列起点(再往前没数据),2026H1 是最新完整半年(7 月起为不完整月份)。
菜篮子指数 = 8 项各自涨跌幅的等权平均(每项先各自归一,再平均)——等权意味着它不是 CPI(CPI 按支出权重),它回答的是"如果八样东西各买同样多,贵了还是便宜了"。
4. 核心代码
import json, urllib.request
from collections import defaultdict
import numpy as np
URL = "https://www.censtatd.gov.hk/api/get.php?id=990-92077&lang=en&full_series=1"
ds = json.loads(urllib.request.urlopen(
urllib.request.Request(URL, headers={"User-Agent": "Mozilla/5.0"}),
timeout=60).read().decode("utf-8"))["dataSet"]
series = defaultdict(dict)
for e in ds:
if e["freq"] == "M" and e["figure"] not in (None, ""):
series[e["FOOD_ITEM"]][int(e["period"])] = float(e["figure"])
rows = []
for code, vals in series.items():
base = np.mean([v for p, v in vals.items() if 202301 <= p <= 202312])
h1 = np.mean([v for p, v in vals.items() if 202601 <= p <= 202606])
rows.append((code, base, h1, (h1 / base – 1) * 100))
for code, base, h1, chg in sorted(rows, key=lambda r: –r[3]):
print(f"{code:<18} {base:>10,.1f} -> {h1:>10,.1f} {chg:+.1f}%")
两个口径细节藏在过滤条件里:freq == "M" 把年度行(Y)排除,figure not in (None, "") 排掉个别空值月份。这段「官方 API → 期间均值 → 涨幅排行」的套路可复用到统计处任何一张物价表,建议收藏备用。
5. 运行结果:八项里六项在跌
Golden thread 83.8 -> 85.5 +2.0%
Tomato 7.9 -> 8.1 +1.8%
Garoupa 100.6 -> 97.3 -3.2%
Live cattle 87,176.6 -> 82,289.8 -5.6%
Mackerel 75.8 -> 66.3 -12.5%
Flowering cabbage 9.2 -> 7.7 -16.3%
Live pig 22,304.3 -> 15,739.7 -29.4%
White cabbage 8.7 -> 5.8 -33.6%
basket index: 100 -> 89.6 (-10.4%)
两个反直觉:猪价跌得比菜狠(-29.4%,内地供应恢复压低活猪批发),鱼类几乎没动(石斑 -3.2%,金线鱼 +2.0%)——"批发通缩"集中在猪肉和叶菜,海鲜是另一回事。所以下次看到"猪肉便宜了"的新闻,这篇数据告诉你那不是错觉,是 42 个月趋势的一部分。
还有一层口径提醒:批发价是上水屠房和批发市场的成交价,它的下跌不经过零售环节就到不了你的菜篮。同一时期如果租金、运输、人工在涨,零售价完全可以按住不动甚至上调——这不是数据打架,是数据在测量不同的环节。
6. 可视化:跌幅排行与菜心的季节脾气


第一张是涨幅排行:绿色六连跌、橙色两连微涨,一眼看清"通缩"集中在哪。第二张是全文最实用的图——菜心 42 个月按月份并排(四色=四个年份),季节规律连续三年重复:9 月批发均价比 12 月贵 37% 到 60%(2023: +60%、2024: +58%、2025: +37%)——夏天台风季 + 北菜淡季把叶菜价格顶上去,冬天来菜通道顺畅价格回落。这张图值得收藏,挑叶菜的季节时机,数据比阿婆的经验好使。
季节图的读法有个诀窍:不要盯着某一年的某一个月,把四条同色系的柱子按月纵向比——2023 年 9 月和 2024 年 9 月都在 10 港元以上、2025 年 9 月 10.00 港元,三年峰值稳定;而 12 月的三根柱子全部落在 7 港元上下。峰值稳定、谷值稳定,中间的波动才是天气噪音。判断"季节规律是否成立",看的正是这种跨年重复性。
7. 批发跌、体感贵:缺口去哪了
把两个数字放在一起才算完整:批发端三年 -10.4%,零售端体感没降。缺口可能的去向包括运输与冷链成本、街市摊位租金与人工、零售加成的粘性——但归因需要零售价数据做同一口径的对照,这篇的批发数据只能证明"批发没涨",不能证明"谁赚走了差价"。数据分析的纪律在此:测到背离,归因留白。也正因为如此,"菜价便宜了"和"买菜贵了"这两句话可以同时为真——它们量的不是同一个环节。
8. 踩坑与避坑
| 活猪/活牛与蔬菜直接比数值 | 8.7 万和 6.3 完全不可比 | 按吨/公斤分组,只比涨跌幅 |
| 年度行(freq=Y)混进月度序列 | 均值被年度值污染 | 过滤 freq == "M" |
| 用 6 月单月当 2026 水平 | 单月受季节扰动 | 上半年均值做基准端点 |
| 把批发跌幅当"买菜便宜了" | 与读者体感冲突掉信任 | 正文明确批发≠零售,背离另行讨论 |
| 菜心季节规律只看一年 | 单年可能是天气偶发 | 三年重复验证(+60%/+58%/+37%) |
这张表建议收藏——第四行是民生数据最重要的纪律:测到什么就说什么,批发和零售之间留白。
9. 总结
42 个月官方数据把"买菜贵不贵"拆成三层:批发端三年通缩 10.4%(六项下跌)、猪比菜跌得狠、叶菜有稳定的 9 月贵 12 月便宜的季节气钟。数据没说"你感觉错了",它说的是你感觉到的涨价不在批发环节——剩下的归因,需要零售端数据接力。物价分析最忌一句话结论,这篇的三层拆法随时可复用到鱼、肉、菜之外的任何食材组合。
代码、口径、验证方法全部可复现,换一张统计处表号就能分析下一个民生主题。这篇也收录进「CodingPlan·八月创作之星博客挑战赛」收官批次。
本文为原创技术实践,数据来自香港政府统计处官方 API(Table 990-92077 平均批发价,2026-09 检索,2026-06 为最新月份);批发价不等于零售价,不构成任何消费或投资建议。
参考链接



