基于 Python 数据分析瑞幸与星巴克全国门店分布及关联关系
引言
近年来,中国咖啡市场经历了爆发式增长。从 2013 年到 2023 年,预计中国人均咖啡消费量上涨了 238%,全国合计咖啡门店数量已超 10 万家。在这一背景下,瑞幸咖啡的崛起尤为引人注目。作为曾经的行业标杆,星巴克几乎成为了过去十几年咖啡文化的代名词,而瑞幸则凭借高性价比和快速扩张策略迅速占领市场。
本文利用 Python 结合 Shapely 库,对瑞幸咖啡与星巴克在全国范围内的门店数量、城市分布及空间关联进行了深度分析。数据显示星巴克更集中于沿海一二线城市,而瑞幸分布更为分散且下沉至三四线城市。通过计算方圆 500 米范围内的重合度发现,平均每个星巴克门店周边存在 0.6 个瑞幸门店,临沂等城市竞争尤为激烈。研究揭示了瑞幸跟随式选址策略及其背后的商业逻辑,为市场布局提供参考。

近年来,中国咖啡市场经历了爆发式增长。从 2013 年到 2023 年,预计中国人均咖啡消费量上涨了 238%,全国合计咖啡门店数量已超 10 万家。在这一背景下,瑞幸咖啡的崛起尤为引人注目。作为曾经的行业标杆,星巴克几乎成为了过去十几年咖啡文化的代名词,而瑞幸则凭借高性价比和快速扩张策略迅速占领市场。
观察发现,瑞幸门店往往选址在星巴克周边,形成了一种独特的竞争共生关系。为了量化这种关系,本文利用 Python 数据分析工具,结合地理信息系统(GIS)技术,对两家品牌的门店数量、区域分布及空间关联进行了深度挖掘。
本次分析任务主要使用以下工具:
注意:由于涉及地理坐标计算,需确保所有数据采用统一的坐标系(通常为 WGS84),并在计算距离时考虑地球曲率或采用投影转换。
为了对比分析,数据集主要包含以下字段:
门店名称:店铺标识。经度:地理位置 X 轴坐标。纬度:地理位置 Y 轴坐标。城市:所属行政区域。注:本分析所用数据集时间为 2022 年,可能存在约 20% 的数量误差,仅供参考趋势分析。
原始数据通常存在缺失值、格式不统一等问题。在导入 Pandas DataFrame 后,需执行以下步骤:
import pandas as pd
import numpy as np
# 假设 df 为读取后的 DataFrame
df['经度'] = pd.to_numeric(df['经度'], errors='coerce')
df['纬度'] = pd.to_numeric(df['纬度'], errors='coerce')
df = df.dropna(subset=['经度', '纬度'])
截至数据集时间(2022 年),星巴克全国门店数量约为 4442 家,瑞幸咖啡全国门店数量约为 3904 家。虽然星巴克门店数仍比瑞幸多 14%,但两者量级已非常接近。瑞幸正以较快的速度扩张,尤其在非一线城市表现强劲。
这表明瑞幸的选址策略更加下沉,没有过度集中在一线城市,而是积极渗透至二三线及内陆市场。
通过可视化热力图可以直观看到:
为了深入探究瑞幸是否跟随星巴克选址,我们使用 Python 和 Shapely 库计算方圆 500 米范围内的重合情况。
Point 对象。import pandas as pd
from shapely.geometry import Point, Polygon
from shapely.ops import unary_union
import math
由于经纬度单位是度,直接 buffer 会产生误差。通常 1 度纬度约等于 111300 米。因此,我们将半径转换为度数。
def create_buffer_polygon(lat, lon, radius_meters=500):
"""
根据经纬度和半径创建多边形缓冲区
:param lat: 纬度
:param lon: 经度
:param radius_meters: 半径(米)
:return: Shapely Polygon 对象
"""
# 近似转换:1 度纬度 ≈ 111300 米
# 经度长度随纬度变化,此处简化处理,实际生产建议使用投影坐标系
degree_radius = radius_meters / 111300.0
center_point = Point(lon, lat)
# buffer 方法生成圆形多边形
circle = center_point.buffer(degree_radius)
return circle
def point_from_coord(lat, lon):
"""
根据经纬度创建点对象
"""
return Point(lon, lat)
为了提高效率,建议先按城市分组,减少不必要的跨城市计算。
# 假设 starbucks_df 和 luckin_df 已加载并清洗完毕
starbucks_df['Polygon'] = starbucks_df.apply(
lambda row: create_buffer_polygon(row['纬度'], row['经度']), axis=1
)
luckin_df['Point'] = luckin_df.apply(
lambda row: point_from_coord(row['纬度'], row['经度']), axis=1
)
results = []
for city in starbucks_df['城市'].unique():
sb_city = starbucks_df[starbucks_df['城市'] == city]
lk_city = luckin_df[luckin_df['城市'] == city]
for idx, row in sb_city.iterrows():
poly = row['Polygon']
count = 0
for _, lk_row in lk_city.iterrows():
if poly.contains(lk_row['Point']):
count += 1
results.append({
'city': city,
'store_id': row['名称'],
'luckin_count': count
})
result_df = pd.DataFrame(results)
性能优化提示:上述循环方式在数据量大时效率较低。在生产环境中,建议使用
geopandas库进行空间连接(sjoin),或使用 R-tree 索引加速查询。
result_df['luckin_count'].mean() # 输出:0.6
result_df['luckin_count'].max() # 输出:7
数据证实了瑞幸确实存在'跟随式'选址策略。星巴克门店通常位于人流密集、消费习惯成熟的区域,这降低了瑞幸的市场教育成本。通过在星巴克周边开店,瑞幸可以低成本获取潜在用户群体。
本文通过可视化看板和 Python 数据分析展示了星巴克和瑞幸咖啡门店的区域分布及关联关系。研究揭示了瑞幸在选址上的精准策略及其背后的商业逻辑,为相关行业的市场布局提供了数据参考。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online