<aside> 📌 Task : 가설 설정

</aside>

테이블

📍 우수 숙소와 그렇지 않은 숙소의 비교

가설 설정 1 : 우수 숙소는 비인기 숙소에 비해 ‘월별 예상 매출’이 높을 것이다.

귀무가설 (H₀) 상위 25% 숙소(우수 숙소)의 월 예상 매출과 하위 25% 숙소(비우수 숙소)의 월 예상 매출은 같다.

대립가설 (H₁) 상위 25% 숙소(우수 숙소)의 월 예상 매출과 하위 25% 숙소(비우수 숙소)의 월 예상 매출은 같다.

<aside> ➕

두 집단을 추가로 비교 분석할 수 있는 컬럼


<aside> 📌 가설 검증

</aside>

<aside> ❓

상위 숙소랑 하위 숙소는 한 달 매출에서 차이가 많이 날까? 얼마나 날까?

combinations = [
    ('도심', 'Entire home/apt'),
    ('도심', 'Private room'),
    ('도심', 'Shared room'),
    ('외곽', 'Entire home/apt'),
    ('외곽', 'Private room'),
    ('외곽', 'Shared room'),
]

results = []

for city_and_suburb, room in combinations:
    subset = df_filtered[
        (df_filtered['city_and_suburb'] == city_and_suburb) &
        (df_filtered['room_type'] == room)
    ]

    # 조합별 25%, 75% 사분위수
    q1 = subset['popularity_score'].quantile(0.25)
    q3 = subset['popularity_score'].quantile(0.75)

    # 상위/하위 25%
    upper = subset[subset['popularity_score'] >= q3]['expected_monthly_revenue']
    lower = subset[subset['popularity_score'] <= q1]['expected_monthly_revenue']

    # 결과 저장
    results.append({
        '조합': f"{city_and_suburb} & {room}",
        '전체 수': len(subset),
        '상위 25% 수': len(upper),
        '하위 25% 수': len(lower),
        '상위 25% 월 매출 중앙값': round(upper.median(), 2),
        '하위 25% 월 매출 중앙값': round(lower.median(), 2),
        '상위 25% 월 매출 평균': round(upper.mean(), 2),
        '하위 25% 월 매출 평균': round(lower.mean(), 2)
    })

expected_monthly_revenue_25 = pd.DataFrame(results)
expected_monthly_revenue_25

스크린샷 2025-07-15 오후 2.25.37.png

☝🏻 그래프로 한 번 ‘중앙값’을 시각화 해볼까?

plt.figure(figsize=(10, 6))

# 데이터를 long-format으로 만들어야 seaborn에서 그리기 좋음
melted = expected_monthly_revenue_25.melt(
    id_vars='조합',
    value_vars=['상위 25% 월 매출 중앙값', '하위 25% 월 매출 중앙값'],
    var_name='그룹',
    value_name='중앙값'
)

sns.barplot(data=melted, x='조합', y='중앙값', hue='그룹')
plt.xticks(rotation=45)
plt.title('조합별 상위/하위 25% 월 매출 중앙값 비교')
plt.ylabel('월 매출 중앙값')
plt.xlabel('')
plt.tight_layout()
plt.show()

image.png

☝🏻 평균이랑 같이 보고 싶은데?


melted = expected_monthly_revenue_25.melt(
    id_vars='조합',
    value_vars=['상위 25% 월 매출 중앙값', '하위 25% 월 매출 중앙값', '상위 25% 월 매출 평균', '하위 25% 월 매출 평균'],
    var_name='그룹',
    value_name='월 매출'
)

# 지표종류 파생
melted['지표'] = melted['그룹'].apply(lambda x: '평균' if '평균' in x else '중앙값')
melted['상하위'] = melted['그룹'].apply(lambda x: '상위' if '상위' in x else '하위')

plt.figure(figsize=(12, 6))
sns.lineplot(
    data=melted,
    x='조합',
    y='월 매출',
    hue='상하위',  
    style='지표',
    markers=True
)

plt.xticks(rotation=45)
plt.title('상위/하위 25% 월 매출 (평균/중앙값)')
plt.ylabel('예상 월 매출')
plt.xlabel('')
plt.tight_layout()
plt.show()

image.png

☝🏻 그냥 봐도 차이가 나긴 하지만 한 번 검증을 해볼까?

from scipy.stats import shapiro, levene, ttest_ind, mannwhitneyu

combinations = [
    ('도심', 'Entire home/apt'),
    ('도심', 'Private room'),
    ('도심', 'Shared room'),
    ('외곽', 'Entire home/apt'),
    ('외곽', 'Private room'),
    ('외곽', 'Shared room'),
]

results = []

for city_and_suburb, room in combinations:
    subset = df_filtered[
        (df_filtered['city_and_suburb'] == city_and_suburb) &
        (df_filtered['room_type'] == room)
    ]

    # 조합별 25%, 75% 사분위수
    q1 = subset['popularity_score'].quantile(0.25)
    q3 = subset['popularity_score'].quantile(0.75)

    # 상위/하위 25%
    upper = subset[subset['popularity_score'] >= q3]['expected_monthly_revenue']
    lower = subset[subset['popularity_score'] <= q1]['expected_monthly_revenue']

    # 정규성
    s_upper = shapiro(upper)
    s_lower = shapiro(lower)

    # 등분산성
    lev = levene(upper, lower)

    # 검정
    if s_upper.pvalue > 0.05 and s_lower.pvalue > 0.05:
        test_type = 't-test'
        t_stat, p_val = ttest_ind(upper, lower, equal_var=(lev.pvalue > 0.05))
    else:
        test_type = 'Mann-Whitney'
        u_stat, p_val = mannwhitneyu(upper, lower, alternative='greater')

    # 저장
    results.append({
        '조합': f"{city_and_suburb} & {room}",
        '전체 수': len(subset),
        '상위 수': len(upper),
        '하위 수': len(lower),
        '상위 평균': round(upper.mean(), 2),
        '하위 평균': round(lower.mean(), 2),
        '상위 중앙값': round(upper.median(), 2),
        '하위 중앙값': round(lower.median(), 2),
        '정규성 상위 p': round(s_upper.pvalue, 4),
        '정규성 하위 p': round(s_lower.pvalue, 4),
        '등분산 p': round(lev.pvalue, 4),
        '검정': test_type,
        'p-value': round(p_val, 5)
    })

test_result = pd.DataFrame(results)
test_result

스크린샷 2025-07-15 오후 2.19.47.png

<aside> 👉🏻

p-value가 유의수준인 0.05보다 작은 0에 가까운 숫자이니 귀무가설 기각! 대립가설 채택!

"상위 25% 숙소는 하위 25% 숙소보다 월 예상 매출이 통계적으로 유의하게 높다.”

</aside>

<aside> 💡

데이터를 통해 확인해 볼 수 있는 것


1️⃣ 평균과 중앙값의 차이 ⬆️

 평균은 이상치의 영향을 크게 받으니 중앙값 기준으로 보면 좋을 듯!

2️⃣ 상위와 하위의 예상 월 매출 차이 ⬆️⬆️⬆️

➖ 도심 + 전체실 격차가 가장 큼

→ 상위 숙소일수록 + 전체실일 때 수익 높은 편

= 예상 월 매출은 접근성(도심)과 객실의 독립성(전체실)이 중요

3️⃣ 상/하위 모두 공유실의 예상 월 매출이 낮음

➖ 공유실은 데이터가 상/하위 도심: 92개 & 외곽 119개로 값이 너무 적기 때문이라 판단

4️⃣ 도심과 외곽 중 도심의 가격대가 전부 높음

→ 접근성이 주는 요소가 크다고 볼 수 있음

</aside>

</aside>

<aside> ❓

그럼 기준이 같은 우수 숙소랑 비우수 숙소에서의 비교가 필요하겠네?

<aside> 1️⃣

가장 차이가 큰 : 도심 + entire_home/apt

</aside>

# 도심 & Entire home/apt 만 필터링
subset = df_filtered[
    (df_filtered['city_and_suburb'] == '도심') &
    (df_filtered['room_type'] == 'Entire home/apt')
]

# 상위/하위 25% popularity_score 기준
q1 = subset['popularity_score'].quantile(0.25)
q3 = subset['popularity_score'].quantile(0.75)

upper = subset[subset['popularity_score'] >= q3]
lower = subset[subset['popularity_score'] <= q1]

results = {
    '지표': [],
    '상위 25% 평균': [],
    '하위 25% 평균': [],
    '상위 25% 중앙값': [],
    '하위 25% 중앙값': []
}

columns_to_compare = [
    'price',
    'expected_monthly_revenue',
    'number_of_reviews',
    'reviews_per_month',
    'availability_365',
    'minimum_nights',
    'calculated_host_listings_count',
    'operating_months'
]

for col in columns_to_compare:
    results['지표'].append(col)
    results['상위 25% 평균'].append(round(upper[col].mean(), 2))
    results['하위 25% 평균'].append(round(lower[col].mean(), 2))
    results['상위 25% 중앙값'].append(round(upper[col].median(), 2))
    results['하위 25% 중앙값'].append(round(lower[col].median(), 2))

comparison_table = pd.DataFrame(results)
comparison_table

스크린샷 2025-07-15 오후 5.43.12.png

<aside> 💡

인사이트 도출


1️⃣ price와 expected_monthly_revenue 컬럼을 봤을 때!


2️⃣ number_of_reviews & rivews_per_month 컬럼을 봤을 때!


3️⃣ availavility 365 컬럼을 봤을 때!

<aside>

<7일 이하 (단기)>

image.png

</aside>


4️⃣ minimum_nights 컬럼을 봤을 때!


5️⃣ calculated_host_listings_count 컬럼을 봤을 때!

image.png


6️⃣ operating_months 컬럼을 봤을 때!

</aside>

<aside> 📌 추가 분석

</aside>

*제가 메인으로 세운 가설이 너무 당연하게 나와서…! ㅜ 우수 비우수를 컬럼별로 저희가 세운 기준에 맞춰 분석을 추가로 해보고 있습니다!

<aside> ❓

</aside>