📙 Fundamentals/ML&DL

🏨 호텔 예약 정보 데이터셋 분석 | 1️⃣ 데이터 전처리

Lento_ 2025. 3. 21. 17:16

👀 INTRO

데이터셋 개요 : 호텔 예약 정보를 포함한 데이터셋

목적 : 예약 취소율에 영향을 미치는 주요 요인을 분석

 

1️⃣  데이터 확인

# 기본 라이브러리 불러오기

# 컬럼 설명

hotel : 호텔명(Resort Hotel 혹은 City Hotel)
is_canceled : 호텔 예약이 취소되었는지(1) 혹은 취소 되지 않았는지(0)를 나타내는 값
lead_time : 호텔 예약 시점부터 고객의 호텔 도착 시점까지의 기간(단위 : 날짜)
arrival_date_year : 고객의 호텔 도착 (연도)
arrival_date_month : 고객의 호텔 도착 (월)
arrival_date_week_number : 고객의 호텔 도착(주)
arrival_date_day_of_month : 고객의 호텔 도착 (일)
stays_in_weekend_nights : 고객이 호텔에 숙박했거나 예약한 주말 밤 수(토요일~일요일)
stays_in_week_nights : 고객이 호텔에 숙박했거나 예약한 주중 밤 수(월요일~금요일)
adults : 예약된 어른의 수
children : 예약된 어린이의 수
babies : 예약된 아기의 수
meal : 예약된 식사 유형
country : 투숙객의 출신 국가
market_segment : 마켓 구분(세분화)
distribution_channel : 예약 유통 채널
is_repeated_guest : 이전에 방문을 하였던 손님인지(1) 아닌지(0)를 나타내는 값
previous_cancellations : 현재 예약 이전에 고객이 취소한 이전 예약 수
previous_bookings_not_canceled : 현재 예약 이전에 고객이 취소하지 않은 이전 예약 수
reserved_room_type : 예약한 룸 타입 코드
assigned_room_type : 배정된 룸 타입 코드
booking_changes : 예약 시점부터 예약 취소/체크인 시점까지 예약에 대한 변경 / 수정 횟수
agent : 예약을 수행한 에이전트 ID
company : 예약을 수행한 회사 ID
days_in_waiting_list : 대기자 명단에 있었던 일수
required_car_parking_spaces : 고객의 특별 요청 사항 개수
total_of_special_requests : 특별 요청 개수
reservation_status : 예약 상태
reservation_status_date : 예약 상태가 마지막으로 업데이트된 날짜

2️⃣  데이터 전처리(결측값)

# 결측값 개수 확인하기

 (결측값 컬럼)

  • 'childern' : 4개
  • 'country' : 488개
  • 'agent' : 16,346개
  • 'company' : 112,593개

# 결측값 처리하기

('childern' 결측값)

: 결측값이 적기 때문에 0으로 대체하여 아이를 동반하지 않는 예약으로 간주

 

('country'결측값)

: 데이터 유실 방지를 위해 'Unknown'으로 대체

 

('agent', 'company' 결측값)

: agent(결측치 비율 13.7%)는 대체 기준이 모호하여 삭제 결정

: company(결측치 비율 94.3%)는 결측치가 너무 많고 예약 취소율과 상관관계가 낮아 삭제 결정

3️⃣  데이터 전처리(중복값)

# 체크인 날짜(연도,월,일) 통합

: 'arrival_date_year', 'arrival_date_month','arrival_date_day_of_month'컬럼 --> 'arrival_date' 하나의 컬럼으로 통합

: YYYY-MM-DD 형식으로 변환

: 'arrival_date_month' 컬럼은 문자열로 저장되어 있으므로, 날짜 형식으로 변환하여 다른 컬럼과 함께 arrival_date로 통합해야 한다.

 

# 중복 컬럼 제거

: 'arrival_date_year', 'arrival_date_month','arrival_date_day_of_month',arrival_date_week_number' 컬럼 삭제

: arrival_date_week_number' 컬럼을 삭제하는 이유

->  arrival_date에서 .week 속성을 사용하면 동일한 정보를 얻을 수 있기에 제거한다.

 

# 중복값 처리

3️⃣  데이터 전처리(이상치)

# 이상치 찾는 함수

- df: DataFrame
- column: 이상치를 찾고 싶은 컬럼명 (연속형 변수만 가능)
- method: "IQR" (사분위수 방법) 또는 "Z-score" 선택 가능

- threshold: IQR 방법일 경우 기본 1.5, Z-score 방법일 경우 기본 3

 

# 히스토그램과 Q-Q플롯으로 각 컬럼에 대한 분포와 이상치 분석

 

[ "lead_time" 이상치 처리 ] 

IQR로 이상치 찾기

- 이상치 : 2406개 존재

'lead_time' 이상치 처리 전

- (히스토그램) : 왼쪽으로 치우친 비대칭적 분포(Positive Skewness)
- (Q-Q Plot) : 정규성을 크게 벗어남. 특히 큰 값에서 극단적인 이상치 존재

상한선 처리 전/후

- lead_time의 최대값(737)이 평균(79)보다 지나치게 크므로 상한선을 365로 설정하여 이상치 값을 대체

📝 MEMO

 
[ np.where() ]
  • 조건에 만족하는 위치 인덱스 찾기
  • 'np.where(배열에 대한 조건문, 참일 때 값, 거짓일 때 값) 형태
  • array(배열)로 반환

'lead_time' 이상치 처리 후

 

[ "previous_bookings_not_canceled" 이상치 처리 ]

IQR로 이상치 찾기

- 이상치 : 3526개 존재

이상치 처리 전

  • (히스토그램) : 대부분 범위 0~5 사이에 있음
  • (Q-Q Plot) : 정규성을 따르지 않고 이상치가 존재한다

상한선 처리 전/후

- 대부분의 값이 0~5 사이에 존재하며, 최대값(72)이 지나치게 크므로 상한선을 50으로 설정하여 이상치 처리

이상치 처리 후

 

[ "previous_bookings_not_canceled" 이상치 처리 ]

IQR로 이상치 찾기

- 이상치 : 1668개

이상치 처리 전

  • (히스토그램) : 대부분 0이고, 일부는 범위 1~2 사이에 있음
  • (Q-Q Plot) : 정규성을 전혀 따르지 않는다.

상한선 처리 전/후

- 대부분의 값이 0이고 일부는 1~2사이에 위치해있고, 최대값(26)이 지나치게 크므로 상한선을 10으로 설정하여 이상치 처리

이상치 처리 후

[ "booking_changes" 이상치 처리 ]

IQR로 이상치 찾기

- 이상치 : 15649개 존재

이상치 처리 전

  • 히스토그램) : 대부분 범위 0~5 사이에 있음
  • (Q-Q Plot) : 정규성을 따르지 않고 이상치가 존재한다

- 대부분의 값이 0이고 일부는 1~2사이에 위치해있고, 최대값(21)이 지나치게 크므로 상한선을 10으로 설정하여 이상치 처리

이상치 처리 후