八个区,均价从 8981 到 19105 元,差 2.13 倍;造数时写的基准价是 2.19 倍。 房源最多的三个区合起来占 44.85%;越贵的区,房源越少。 报均价必须连套数一起报——郊县只有 60 套,它的均价分量和别人不一样。
上一篇把数据洗到 1184 行,这一篇开始分组统计,用的是第 3 章的 groupby 和第 7 章的对比思路。 分组统计看着简单,难的是「分组之后该看哪几个数」——这一篇就是回答这个。
一、一句 groupby 出四列
按区域分组,一次要四个数:套数、占比、均价、平均总价。
agg 里给每个指标指定聚合函数:套数用 count,均价和总价用 mean。
占比要自己算:这一组的套数除以总行数。它是派生列,不是原表里有的。
排序也有讲究。比均价就按均价排,比套数就按套数排,两张表排法不一样,结论也不一样。
二、两个「均价」别混
表里有两个「均价」:一个是元每平米(单价),一个是万元每套(总价)。 这次排出来,城中 19105 元每平米、平均总价 172.36 万;郊县 8981 元、86.69 万。 两个排名这次一致,但不保证永远一致。豪宅区可能单价高、套均总价也高; 小户型扎堆的核心区单价高、总价却不高。
所以报告里必须写清是哪一个。只写「均价」,读者会按自己习惯的那个理解。
三、贵在哪,便宜在哪
均价最高城中 19105 元,最低郊县 8981 元,差 2.13 倍。 造数据时写进去的基准价是 21000 和 9600,正好 2.19 倍。跑出来 2.13 倍。 两个数差一点,是装修、房龄、楼层三个系数各叠了一层,再加上噪声。
这句话在真实项目里很重要:理论值和实测值总有差,差得少说明机制对,差得多说明还有别的因素。 第二名城东 16577 元,比城中低 13.2%,两个区基本在一个档上——排名第一和第二之间不一定有断层。
四、占比:市场的形状
套数最多的三个区是城东 195 套、城北 169 套、城南 167 套,合起来占 44.85%。 贵的区房源少,便宜的区房源多——城中只占 10.14%,郊县只有 5.07%。 这个形状放到业务里就有用:想找成交快的房子,去城东城北;想找便宜货,去经开郊县。
只报占比,会以为市场很均衡;只报均价,会以为贵的区是主流。两张表一起看才对。
五、样本量:小样本的均价不能当结论
八个区的套数从 60 到 195,还算均衡,这次可以横向比。 但要养成习惯:报区域均价,一定把套数一起报。 套数 60 的区,多两套豪宅就能把均价拉上去几百块;套数 600 的区,多两套几乎没影响。
下结论前先看样本量,是分组统计的铁律。样本 5 个的组,那个均值只是「这 5 个的平均」。 最后一句话总结:城中 19105 元最贵,郊县 8981 元最便宜,城东 195 套房源最多。
六、动手 Demo:区域二手房均价与占比分析
一句 groupby 加 agg 出套数、均价、平均总价,占比自己算,最后按均价排序。 读的是清洗后的那份,1184 行。
import pandas as pd
df = pd.read_csv("二手房数据_clean.csv")
g = df.groupby("区域").agg(套数=("编号", "count"),
均价=("单价", "mean"),
平均总价=("总价", "mean"))
g["占比"] = g["套数"] / len(df) * 100
g = g.sort_values("均价", ascending=False)
print(g.round(2).to_string())
print("最贵 %s %d 元,最便宜 %s %d 元,差 %.2f 倍"
% (g.index[0], g["均价"].iloc[0], g.index[-1], g["均价"].iloc[-1],
g["均价"].iloc[0] / g["均价"].iloc[-1]))
print("套数前三合起来占 %.2f%%"
% (g["套数"].nlargest(3).sum() / len(df) * 100))
实跑输出:
--------------------------------------------------------------------
区域二手房均价与占比分析
--------------------------------------------------------------------
① 各区有多少套
--------------------------------------------------------------------
| 区域 | 套数 | 占比 | 均价(元) | 平均总价(万) |
|---|---:|---:|---:|---:|
| 城中 | 120 | 10.14% | 19105 | 172.36 |
| 城东 | 195 | 16.47% | 16577 | 157.87 |
| 城西 | 162 | 13.68% | 15352 | 143.56 |
| 高新 | 149 | 12.58% | 14765 | 132.91 |
| 城南 | 167 | 14.10% | 14334 | 130.79 |
| 城北 | 169 | 14.27% | 12818 | 119.63 |
| 经开 | 162 | 13.68% | 11265 | 108.97 |
| 郊县 | 60 | 5.07% | 8981 | 86.69 |
一共 1184 套,八个区。
套数最多的是 城东,195 套;最少的是 郊县,60 套。
② 均价:贵在哪,便宜在哪
--------------------------------------------------------------------
均价最高 城中,19105 元;最低 郊县,8981 元;差 2.13 倍。
造数时写的基准价是 21000 和 9600,正好 2.19 倍;跑出来是 2.13 倍。
两个差一点,是装修、房龄、楼层三个系数和噪声各自加了一层。
排名第二的是 城东,16577 元;比第一名低 13.2%,两个区基本在一个档上。
均价是「每平米多少钱」,不是「一套多少钱」。两个数经常给出不同的排名。
③ 占比:房源都堆在哪
--------------------------------------------------------------------
按套数排,前三名是 城东 195 套、城北 169 套、城南 167 套。
前三名合起来占 44.85%。
占比和均价要摆在一张表里看:贵的区房源少,便宜的区房源多,这才是市场的形状。
只报占比,会以为市场很均衡;只报均价,会以为贵的区是主流。两个一起看才对。
④ 样本量:小样本的均价不能当结论
--------------------------------------------------------------------
这次每个区的套数都在 60 以上,样本量还算均衡,均价可以横向比。
下结论前先看样本量,是分组统计的铁律。样本 5 个的组,均值只是「这 5 个的平均」。
! 真项目里报区域均价,一定要把套数一起报。只报均价不报样本量,等于给了半个结论。
⑤ 结论怎么写
--------------------------------------------------------------------
一句话:城中最贵(19105 元),郊县最便宜(8981 元),城东房源最多(195 套)。
结论要能一句说完,才说明真的看懂了。说不成一句,就是还没想清楚。
下一篇换两个维度:装修程度和户型。这两列都是分类变量,统计的是频数和均价。
agg 里写 ("编号", "count") 是「命名聚合」:左边是新列名,右边是要算的列和函数。
count 数非空值,size 数行数。编号没有空,两个结果一样;换成一列有空值的字段就不同了。
排序放在算完占比之后,顺序反了排序会打乱,占比那一列就对不上号了。
30 秒实验
- 把
count换成size,看套数变没变,想想什么情况下会变。 - 按套数重新排一次序,看前三名换成哪三个区。
- 想一想:为什么郊县只有 60 套,均价却未必最不稳?
常见误区
- 把均价窄化成「元每平米」:不注意就会把「套均总价」也当均价,两个数差两个数量级。
- 只报均价不报套数:小样本的均价波动大,读者没法判断该信几分。
- 占比忘了除总数:直接拿套数当占比,加起来一百多,自己都看不出错。
- 排序和计算顺序颠倒:先排序再算占比,
len(df)没错,但行号对不上就白算。
自测三问(点开对答案)
1. 「均价」这个词这次指哪两个数? —— 单价(元每平米)和套均总价(万元每套)。两个排名可能不一样,报告里必须写清。 2. 实测 2.13 倍,造数写的是 2.19 倍,说明数据错了吗? —— 没写错。系数叠了装修、房龄、楼层再加噪声,差一点是正常的。差很多才要查。 3. 为什么报区域均价一定要带套数? —— 套数少的区,几套异常房就能把均值拉偏。不带套数,读者没法判断这个均价可信度多高。区域看完了。下一篇换两个维度:装修程度和户型,都是分类变量。
- ☐ (本篇完,下一篇 11.5 装修程度与热门户型)