[수업 목표]
•
Airbnb 분석 프로젝트를 통해 **데이터 분석 5단계(문제 정의–수집–전처리–EDA–보고)**의 전체 프로세스를 이해한다.
•
실습을 통해 결측치 처리, 이상치 제거, 문자열·날짜·범주형 자료 변환 등 핵심 전처리 기술을 익힌다.
•
Room Type, 가격, 리뷰, 계절성, 위치 등을 활용하여 EDA(탐색적 데이터 분석)의 패턴 분석 방법을 이해한다.
•
Boxplot, IQR, 월별 리샘플링, 리뷰 Long-tail 구조 등 통계적·시각적 분석 기법을 실제 Airbnb 데이터에 적용한다.
•
최종적으로 “데이터 기반 인사이트 도출과 실무 의사결정 지원”이 가능한 분석 보고서를 구성하는 방법을 익힌다.
[목차]
1.
문제 정의(Problem Definition)
2.
데이터 수집(Data Collection)
3.
데이터 전처리(Cleaning & Preprocessing)
4.
EDA: Room Type, Price, Review, Location, Seasonality 분석
5.
Boxplot·IQR을 통한 가격 이상치 탐색
6.
월별 가격·예약률 리샘플링 및 패턴 분석
7.
리뷰 Long-tail 구조 및 인기 숙소 특성 분석
8.
위치 기반 분석(지역별 가격·리뷰·숙소 분포)
9.
결과 요약 및 실무 전략 제안(호스트·마케팅·경영진)
0. 데이터 분석 방법론 - 5단계
•
문제 정의 (Problem Definition)
◦
문제를 잘못 정의하면, 어떤 분석을 해도 의미가 없다.
◦
팀 프로젝트에서 가장 중요한 단계이자, 분석의 방향을 결정하는 핵심 출발점이다.
•
데이터 수집 (Data Collection) → 데이터 셋 제공
◦
"좋은 데이터" 확보가 분석 품질을 결정한다. 마치 요리에 필요한 재료를 고르는 과정과 같다.
•
데이터 전처리 (Data Cleaning & Preprocessing)
◦
전체 분석 시간의 **60~80%**를 차지하는 필수 단계. 깨끗한 데이터 없이 좋은 분석은 나올 수 없다.
•
데이터 분석 (Exploratory & Statistical Analysis)
◦
데이터를 "읽는 능력"을 기르는 단계. 파이썬, Pandas, Matplotlib/Seaborn, Plotly 등을 활용해
→ 트렌드 / 패턴 / 상관관계 / 분포 등을 확인한다.
•
결과 도출 및 보고 (Insight & Reporting)
◦
분석의 끝은 항상 "설득"이다.
◦
데이터로 이야기하고, 분석 결과를 누구나 이해할 수 있는 형태로 전달하는 단계이다.
1. 문제 정의 (Problem Definition)
•
Airbnb 숙박 시장은 전통 호텔 산업과 경쟁하며 지역 경제 및 숙소 운영자 의사결정에 큰 영향을 미친다.
•
특히 시애틀은 관광·비즈니스 수요가 높아 숙소 유형·가격·입지가 수익성에 결정적인 차이를 만든다.
해결해야 하는 문제
•
어떤 요인이 숙소 가격(Price)에 가장 큰 영향을 미치는가?
•
계절·요일별 가격/예약 패턴은 어떤가?
•
리뷰 평점·리뷰 수는 예약률에 어떤 영향을 주는가?
•
도심 vs 교외 등 지역별 숙소 특성은 어떻게 다른가?
의사결정을 돕는 방향
•
호스트가 가격 전략을 어떻게 가져가야 하는지
•
신규 호스트는 리뷰를 어떻게 확보하고 경쟁력을 높일지
•
Airbnb 본사는 지역별·계절별 마케팅 전략을 어떻게 수립할지
→ 호스트에게 수익 극대화 전략을 제시하고, Airbnb 본사에서는 서비스 개선과 마케팅 방향성을 잡는 근거로 활용하는 것이 이번 비즈니스 목표이다!
최종 산출물
•
숙소 유형별 가격 분포 분석
•
지역 기반 시각화(숙소 분포 지도)
•
성수기/비수기 가격 및 예약 가능률 패턴
•
리뷰–가격/예약률 상관관계 분석
•
호스트/마케팅/경영진을 위한 전략 가이드라인
2. 데이터 수집 (Data Collection)
•
사용한 데이터는 Inside Airbnb 프로젝트에서 공개한 시애틀 Airbnb 데이터셋.
•
공개된 CSV형식이며 Kaggle에서도 동일한 데이터 이용 가능.
사용 데이터셋
•
listings.csv → 숙소 정보(가격, 위치, 유형, 리뷰 점수 등)
•
calendar.csv → 2016.1.1 ~ 2017.1.1 날짜별 예약 가능 여부 및 가격
•
reviews.csv → 숙소 리뷰(작성 날짜, 텍스트, 리뷰어 ID)
외부 데이터 필요 여부
•
호텔/Airbnb 경쟁 비교까지 하려면 추가 데이터가 필요하지만
•
본 프로젝트 목표(숙소 내부 패턴 분석)에는 현재 데이터만으로 충분하다.
데이터 접근 방식
•
CSV 파일 로컬 로드
•
(필요 시) API/크롤링은 사용하지 않음
•
모든 데이터는 개인정보 비식별 → 팀 협업에 적합
데이터 로드 코드
import pandas as pd
listings = pd.read_csv('listings.csv')
calendar = pd.read_csv('calendar.csv')
reviews = pd.read_csv('reviews.csv')
Python
복사
3. 데이터 전처리 (Data Cleaning & Preprocessing)
•
Airbnb 데이터는 결측치·형식 오류·이상치가 꽤 많기 때문에 전처리 품질이 분석 정확도를 크게 좌우했다.
결측치 처리
•
결측치(Missing Values)
◦
reviews.csv의 경우 텍스트가 없는 리뷰 존재
◦
review_scores_rating이 없는 숙소 존재 (신규 숙소일 가능성 있음)
◦
neighbourhood 정보가 비어 있는 숙소도 발견됨
•
review_scores_rating → "No Rating"
•
neighbourhood → "Unknown"
•
리뷰 텍스트 없음 → 해당 행 삭제
listings['review_scores_rating'] = listings['review_scores_rating'].fillna("No Rating")
listings['neighbourhood'] = listings['neighbourhood'].fillna("Unknown")
reviews = reviews.dropna(subset=['comments'])
Python
복사
이상치 처리
•
$0, $10,000 이상 등 비정상 가격 제거 / 기준: $10 이상 ~ $1,000 미만 유지
listings['price'] = listings['price'].replace('[\$,]', '', regex=True).astype(float)
listings = listings[(listings['price'] > 10) & (listings['price'] < 1000)]
Python
복사
데이터 형식 통일
•
가격 데이터 이슈
◦
price 컬럼에 달러 기호($), 쉼표(,)가 포함되어 있어 숫자로 변환 필요
•
price → 숫자(float)
•
available → True/False
•
날짜 컬럼 → datetime
•
room_type → category
calendar['available'] = calendar['available'].map({'t': True, 'f': False})
calendar['date'] = pd.to_datetime(calendar['date'], errors='coerce')
calendar['price'] = calendar['price'].replace('[\$,]', '', regex=True).astype(float)
listings['room_type'] = listings['room_type'].astype('category')
Python
복사
(4) 중복 및 일관성 검토
•
숙소 ID는 고유해야 하지만, listings.csv와 calendar.csv, reviews.csv 간 조인 시 누락/불일치 가능성 있음
•
calendar.csv에는 같은 숙소가 여러 날짜에 반복 기록되어 있으므로, 분석 목적에 따라 집계 필요
•
숙소 ID 기준으로 listings/calendar/reviews 병합
•
중복 ID 및 일관성 없는 값 제거
데이터 병합 코드
df = listings.merge(calendar, left_on='id', right_on='listing_id', how='inner')
df = df.merge(reviews, left_on='id', right_on='listing_id', how='left')
Python
복사
(5) 파생 변수 생성 (Feature Engineering)
•
월별 평균 가격
•
월별 예약 가능률
•
리뷰 수 기반 인기 지수
월별 리샘플링 코드
calendar_monthly = (
calendar.groupby(calendar['date'].dt.to_period("M"))
.agg({'price': 'mean', 'available': 'mean'})
)
Python
복사
4. 데이터 분석 (Exploratory & Statistical Analysis)
•
EDA를 통해 트렌드–패턴–상관관계–군집 구조를 도출한다.
숙소 유형(Room Type) vs 가격(Price)
•
Entire home/apt > Private room > Shared room
→ 집 전체 대여는 개인실 대비 평균 2배 이상 비쌈
Room Type | 평균 가격 |
Entire home | 약 $155 |
Private room | 약 $75 |
Shared room | 약 $47 |
•
이는 가격 결정의 1차적 요인이 숙소 유형임을 보여준다.
가격 분포 시각화 코드
import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize=(10,5))
sns.boxplot(data=listings, x='room_type', y='price')
plt.show()
Python
복사
시간 흐름 분석 – 월별 가격 & 예약 가능률
•
1~3월: 가격 낮음(비수기)
•
6~8월: 가격 상승 + 예약 가능률 하락 → 여름 성수기
•
12월: 가격 최고점($175 수준) → 겨울 휴가 성수기
월별 가격·예약률 시각화 코드
calendar_monthly['price'].plot(figsize=(12,4), title='Monthly Average Price')
calendar_monthly['available'].plot(figsize=(12,4), title='Monthly Availability')
plt.show()
Python
복사
리뷰 데이터 분석
•
리뷰 수 Long-tail
◦
대부분 50개 이하
◦
일부 숙소는 300~470개의 리뷰 보유 → 시장 집중 구조
•
인기 숙소 특징
◦
Downtown / Capitol Hill / U District
◦
접근성 좋음
◦
아파트/스튜디오 형태 다수
리뷰 상위 10개 시각화 코드
top_reviews = listings.nlargest(10, 'number_of_reviews')
plt.figure(figsize=(12,4))
plt.bar(top_reviews['id'], top_reviews['number_of_reviews'])
plt.show()
Python
복사
위치 기반 패턴 분석
•
도심에 숙소가 집중
•
도심일수록 가격·리뷰 수 모두 높음
→ 입지가 수익성과 강하게 연결됨
지도 시각화 기본 코드
import folium
m = folium.Map([47.6062, -122.3321], zoom_start=12)
Python
복사
5. 결과 도출 및 보고 (Insight & Reporting)
핵심 인사이트
•
① Room Type = 가격 결정의 가장 강력한 변수
◦
Entire home/apt는 Private room의 2배 가격 이상
•
② 계절성(Seasonality)은 가격·예약률을 크게 좌우
◦
성수기: 가격 상승 + 예약 가능률 ↓
◦
비수기: 장기 숙박 및 할인 정책 필요
•
③ 리뷰 수 = 신뢰도 + 예약률
◦
20~30개 리뷰만 확보해도 예약률 급등
◦
신규 호스트에게 가장 중요한 초기 전략
•
④ 위치(Location)가 성과를 규정
◦
도심 = 높은 가격 + 높은 리뷰 수 + 수요 집중
◦
교외 = 가격 경쟁력 전략 필요
의사결정 도움
•
성수기 가격 인상
•
비수기 주중 할인·장기 숙박 할인
•
신규 호스트: 리뷰 확보 전략
•
도심 지역 중심 프로모션
•
시즌별 테마 마케팅
•
평점·리뷰 기반 추천 시스템 개선
•
가격 가이드라인 정책
•
신규 호스트 지원 프로그램
•
성수기 수요 예측 기반 전략
전체 코드 모음
•
모든 전처리·병합·EDA 코드가 한 번에 정리된 버전입니다.
# -----------------------# 데이터 로드# -----------------------import pandas as pd
listings = pd.read_csv('listings.csv')
calendar = pd.read_csv('calendar.csv')
reviews = pd.read_csv('reviews.csv')
# -----------------------# 결측치 처리# -----------------------
listings['review_scores_rating'] = listings['review_scores_rating'].fillna("No Rating")
listings['neighbourhood'] = listings['neighbourhood'].fillna("Unknown")
reviews = reviews.dropna(subset=['comments'])
# -----------------------# 이상치 처리# -----------------------
listings['price'] = listings['price'].replace('[\$,]', '', regex=True).astype(float)
listings = listings[(listings['price'] > 10) & (listings['price'] < 1000)]
# -----------------------# 형식 통일# -----------------------
calendar['available'] = calendar['available'].map({'t': True, 'f': False})
calendar['date'] = pd.to_datetime(calendar['date'], errors='coerce')
calendar['price'] = calendar['price'].replace('[\$,]', '', regex=True).astype(float)
listings['room_type'] = listings['room_type'].astype('category')
# -----------------------# 데이터 병합# -----------------------
df = listings.merge(calendar, left_on='id', right_on='listing_id', how='inner')
df = df.merge(reviews, left_on='id', right_on='listing_id', how='left')
# -----------------------# 월별 리샘플링# -----------------------
calendar_monthly = (
calendar.groupby(calendar['date'].dt.to_period("M"))
.agg({'price': 'mean', 'available': 'mean'})
)
Python
복사






