스타벅스와 경쟁 커피숍의 입지 전략 분석
2025. 12. 8. 16:48ㆍAI활용 멀티모달&MCP 과정
스타벅스와 경쟁 커피숍의 입지 전략 분석
서울시 스타벅스 매장과 주요 커피 프랜차이즈(이디야·메가커피·빽다방·컴포즈커피 등) 매장 사이의 거리를 계산해서 “스타벅스 옆에 들어선다”는 속설이 실제로 맞는지 데이터를 통해 확인해보는 실습입니다.
학습 목표
이번 실습을 통해 다음 내용을 익힐 수 있습니다:
- 공공데이터와 크롤링 데이터를 pandas로 불러와 전처리하는 방법
str.contains()와 정규표현식을 활용한 다중 키워드 필터링- Haversine 공식을 이용해 위경도로 실제 거리(m) 계산하기
merge(how='cross')로 모든 조합 만들기groupby()+agg()로 브랜드별 평균·최소 거리 및 매장 수 집계- pyecharts로 인터랙티브 파이 차트와 타임라인 시각화하기
목차
- 1. 데이터 불러오기 및 기본 전처리
- 2. 경쟁 커피숍 데이터 필터링
- 3. 상호명 정리 (정규화)
- 4. 스타벅스 × 경쟁점 크로스 조인
- 5. Haversine 공식으로 거리 계산
- 6. 브39랜드별 최소·평균 거리 분석
- 7. 거리 기준 함수 만들기
- 8. pyecharts로 인터랙티브 시각화
- 9. 오늘 공부한 내용 요약
1. 데이터 불러오기 및 기본 전처리
# 스타벅스 서울 매장 데이터 (이미 크롤링 완료 가정)
df_starbucks = pd.read_csv('/본인의 구글드라이브 경로/starbucks_seoul.csv')
# 컬럼명 정리
df_starbucks = df_starbugs.set_axis(['지점명', '지점주소', '지점위도', '지점경도'], axis=1) \
.reset_index(drop=True)
# 서울시 상가(상권) 정보 공공데이터
df = pd.read_csv('/본인의 구글드라이브 경로/소상공인시장진흥공단_상가(상권)정보_서울_202409.csv',
low_memory=False)
# low_memory=False → 대용량 CSV를 한 번에 읽어 메모리 부족 방지



2. 경쟁 커피숍 데이터 필터링
# 필터링할 브랜드 리스트
shop = ['이디야', '이디아커피', '올리브영', '컴포즈커피',
'빽다방', '백다방', '메가커피', '메가엠지씨', '메가MGC']
# | (OR) 연산자로 한 번에 검색
pattern = '|'.join(shop)
df_shop = df[df["상호명"].str.contains(pattern, case=False, na=False)].copy()
str.contains()는 특정 문자열이 포함되어 있으면 True를 반환합니다. case=False로 대소문자 구분을 없애고, na=False로 결측치는 False 처리합니다.

3. 상호명 정리 (정규화)
# 필요한 컬럼만 추출
df_shop = df_shop.dropna(subset=['상호명']) \
.iloc[:, [0, 1, 14, 37, 38]] \
.reset_index(drop=True)
# 같은 브랜드인데 이름이 다른 경우 통일
df_shop['상호명'] = df_shop['상호명'].str.replace('메가엠지씨', '메가커피', regex=False)
df_shop['상호명'] = df_shop['상호명'].str.replace('메가MGC', '메가커피', regex=False)
df_shop['상호명'] = df_shop['상호명'].str.replace('이디아커피', '이디야', regex=False)
df_shop['상호명'] = df_shop['상호명'].str.replace('백다방', '빽다방', regex=False)

4. 스타벅스 × 경쟁점 크로스 조인
# 모든 스타벅스와 모든 경쟁 매장의 조합 생성 (Cartesian Product)
df_cross = df_shop.merge(df_starbugs, how='cross')

5. Haversine 공식으로 거리 계산
# !pip install haversine
from haversine import haversine
# 두 지점의 (위도, 경도)를 튜플로 묶어서 거리 계산 (미터 단위)
df_cross['거리'] = df_cross.apply(
lambda row: haversine(
(row['위도'], row['경도']), # 경쟁 매장 좌표
(row['지점위도'], row['지점경도']), # 스타벅스 좌표
unit='m'
),
axis=1
)
Haversine 공식은 지구를 완벽한 구로 가정하고 위도·경도로 두 지점 사이 최단거리를 계산합니다.
unit='m' (미터), unit='km (키로미터)

6. 브랜드별 최소·평균 거리 분석
# 각 경쟁 매장과 가장 가까운 스타벅스 거리
df_dis = df_cross.groupby('상호명')['거리'].min().reset_index()
# 브랜드별 평균 거리와 매장 수
df_dis.groupby('상호명')['거리'].agg(['mean', 'count'])


7. 거리 기준 함수 만들기
def distance(x):
# x미터 이내에 있는 매장만 필터링
return df_dis[df_dis['거리'] <= x] \
.groupby('상호명')['거리'] \
.agg(['mean', 'count'])
# 예시: 100m 이내 매장 수와 평균 거리
distance(100)

8. pyecharts로 인터랙티브 시각화
# !pip install pandasecharts pyecharts
# 파이그래프로 표현하기
import IPython
from pandasecharts import echart
df_100.echart.pie(x='상호명', y='count', figsize=(600, 400),
radius=['20%', '60%'], label_opts={'position':'outer'},
title='커피 프렌차이즈의 입점전략은 과연 스타벅스 옆인가?',
legend_opts={'pos_right':'0%', 'orient':'vertical'},
subtitle='100m 이내 매장수', init_opts={'bg_color': 'white'}).render()
IPython.display.HTML(filename='render.html')
# 타임라인 파이그래프로 표현하기
from pyecharts.charts import Timeline
from pyecharts import options as opts
from pandasecharts import echart
import IPython
tl = Timeline(init_opts=opts.InitOpts(width="800px", height="500px"))
for dist in [1000, 500, 100, 50, 30]:
df_tmp = distance(dist).reset_index()
pie = (df_tmp.echart
.pie(x='상호명', y='count',
radius=["20%", "70%"],
label_opts=opts.LabelOpts(position="outer"))
.set_global_opts(
title_opts=opts.TitleOpts(
title="스타벅스와의 거리별 경쟁 매장 수",
subtitle=f"{dist}m 이내"),
legend_opts=opts.LegendOpts(orient="vertical", pos_right="0%"))
)
tl.add(pie, f"{dist}m")
tl.render()
IPython.display.HTML(filename="render.html")


오늘 공부한 내용 요약
오늘은 실제 공공데이터와 크롤링 데이터를 활용해 다음과 같은 분석 흐름을 완성했습니다:
- 대용량 CSV 안전하게 불러오기 →
low_memory=False - 다중 키워드로 상호명 필터링 →
str.contains()+ 정규식 - 상호명 정규화 →
str.replace() - 크로스 조인으로 모든 조합 생성 →
merge(how='cross') - Haversine 공식으로 실제 거리 계산 →
haversine라이브러리 groupby()+agg()로 브랜드별 통계- 거리 기준 함수화 및 pyecharts 타임라인 파이차트 시각화
이 과정을 익히면 “어떤 프랜차이즈가 스타벅스를 얼마나 의식하며 입점하는가” 같은 실무형 입지 분석 프로젝트를 혼자서도 충분히 수행할 수 있습니다!
| 명령어 / 함수 | 설명 | 주요 옵션/인자 |
|---|---|---|
pd.read_csv(..., low_memory=False) |
대용량 CSV를 메모리 문제 없이 읽어오기 | low_memory=False |
str.contains() |
문자열에 특정 텍스트 포함 여부 확인 | case=False, na=False |
merge(how='cross') |
두 데이터프레임의 모든 행 조합 생성 (카티션 곱) | how='cross' |
haversine() |
위경도로 지구 표면 거리 계산 | unit='m' 또는 'km' |
groupby().agg(['mean','count']) |
그룹별 다중 집계 동시에 수행 | mean, min, count 등 |
pyecharts / pandasecharts |
인터랙티브 차트(파이, 타임라인 등) 생성 | radius, label_opts, legend_opts 등 |
'AI활용 멀티모달&MCP 과정' 카테고리의 다른 글
| House Rent Prediction 데이터셋 분석과 회귀 모델링 (0) | 2025.12.22 |
|---|---|
| Git 기초부터 GitHub 협업까지 완벽 정리 (0) | 2025.12.10 |
| 소상공인 상가(상권)정보 데이터로 서울 지도 시각화하기 (0) | 2025.11.28 |
| 서울시 공공자전거 실시간 대여소 정보 API 호출 (0) | 2025.11.27 |
| Online Retail, Kaggle (0) | 2025.11.26 |