본문 바로가기
내가 하는 데이터분석/내가 했던 공모전

공연예술통합전산망(KOPIS) 빅데이터 분석 공모전 1편 가설1

by Pymoon 2022. 12. 16.

20220801 ~ 20221019

 

 

우연한 계기로 처음 보는 2명의 팀원들과 같은 뜻을 가지고 공모전에 참여하게 되었다.

 

주제는 공연소비, 유통 측면에서 시장 문제점을 해결 및 발전시킬 수 있는 범주 내 자유주제였다.

 

우리는 원작이라는 키워드에 초점을 두기로 했다.

 

따라서, 우리 주제는

 

 

원작과 원작을 각색한 공연과의 상관관계 도출 및 원작을 기반으로 각색 공연 관객 수 예측이다.

 

 

 

가설1 : 원작이 존재하는 연극이 그렇지 않은 연극에 비해 높은 흥행을 기록할 것이다.

 

여기에선 가설1에 대한 내용만을 다룰 것이다.

 


 

 

데이터가 10G에 가까웠기 때문에 데이터를 다루기가 매우 부담스러웠다.

 

우리는 데이터를 연도별로(2019, 2020, 2021, 2022) 나누어서 따로 작업하고 나중에 합치기로 했다.

 

 

 

1
2
3
4
5
6
7
8
from matplotlib import pyplot as plt
from scipy.stats import *
import seaborn as sns
import pandas as pd
import os
os.chdir(r"C:\Users\82102\Desktop\kopis 공모전")
 
os.listdir("2019")
cs

 

> 하지만 2019년 데이터만해도 파일이 20개 정도 되었기 때문에 이를 병합하는 작업이 필요했다.

 

 

 

1
2
3
4
5
6
merged_df_2019 = pd.DataFrame()
 
for file in os.listdir("2019"):
    if "kopis.xlsx" in file:
        df = pd.read_excel("2019/" + file
        merged_df_2019 = pd.concat([merged_df_2019, df], axis=0, ignore_index=True
cs

 

> 자, merged_df_2019라는 변수 안에 2019년의 모든 데이터가 들어갔다. 이제 이걸로 분석을 실행하고자 한다.

 

 

 

1
dup_merged_df_2019 = merged_df_2019.drop_duplicates(['공연코드'])
cs

 

> 우리는 공연코드별로 파생변수인 관객 수를 산출해야 하므로 우선 중복되는 공연코드를 제거한 후 따로 변수할당 해준다.

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 관객수 파생변수 생성
df1 = merged_df_2019[['공연코드','예매/취소구분']].copy()
df2 = pd.DataFrame()
df3 = pd.DataFrame()
for i in df1['공연코드'].unique().tolist():
    df2 = df1[df1['공연코드']==i].copy()
        
    cnt1 = len(df2[df2['예매/취소구분']==1]) # 예매/취소구분이 1인 개수
    cnt2 = len(df2[df2['예매/취소구분']==2]) # 예매/취소구분이 2인 개수
    df2['관객수'= cnt1 - cnt2 # 1에서 2를 뺀 개수를 관객수
    df2 = df2.drop('예매/취소구분', axis=1)
        
    df3 = pd.concat([df3, df2], axis = 0).copy()
    df3 = df3.drop_duplicates()
    
df3 = df3.groupby('공연코드')['관객수'].sum()
cs

 

> 위 코드는 공연코드와 예매/취소구분 컬럼을 통해서 공연코드별 관객 수를 산출하는 알고리즘을 가지는 코드이다.

 

 

 

1
2
df3 = pd.DataFrame(data=df3)
df4 = pd.merge(dup_merged_df_2019, df3, left_on='공연코드', right_on='공연코드')
cs

 

> 공연코드의 중복을 제거한 데이터와 공연코드별로 산출한 관객 수 컬럼을 공연코드라는 컬럼을 기준으로 병합한다.

 

 

 

1
final_2019 = df4.set_index('공연코드')
cs

 

> index를 공연코드로 해서 final_2019라는 변수에 데이터를 할당시켜준다.

 

 

 

1
2
3
4
5
# 극작가명 컬럼에 각색이라는 키워드여부에 따라 각색여부 판단
row_indexes=final_2019.loc[final_2019['극작가명'].str.contains('각색', na=False)].index
final_2019.loc[row_indexes,'각색여부']=1
row_indexes=final_2019.loc[~final_2019['극작가명'].str.contains('각색', na=False)].index
final_2019.loc[row_indexes,'각색여부']=0
cs

 

> 각색 여부를 판단하기 위해 극작가명 컬럼에 각색이라는 키워드를 기준으로 0 또는 1로 구분 지어준다.

 

 

 

1
2
3
4
5
6
# 불필요한 컬럼 제거
final_2019.drop(['시설특성','공연일시','예매/취소구분','장당금액','공연시작일자','공연종료일자','장르명','원작자명','극작가명'
                 '수상실적','관람연령','축제 여부','내한공연 여부','오픈런 여부','단독판매여부'], axis=1, inplace = True)
# 불필요한 용량 제거
final_2019['각색여부'= final_2019["각색여부"].astype('int8')
final_2019['관객수'= final_2019["관객수"].astype('int32')
cs

 

> 가설1을 검정하는데 있어서 불필요한 컬럼에 대해서는 과감하게 제거해주고, 불필요한 용량을 차지하는 부분도 덜어주는 과정을 거침으로서 가설1 진행에 대한 준비를 마친다.

 

 

 

1
2
# 관객수 데이터 중 음수 제거
final_2019 = final_2019[final_2019['관객수']>0]
cs

 

> 중간에 알게 된 사실이지만 관객 수가 음수값이 나오는 경우가 몇몇 있었다. 이런 모순적인 부분은 데이터를 제공해 준 기관에서도 인정한 부분이었기 때문에 찝찝하지만 음수를 제거해 주는 과정을 추가로 넣어준다.

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
%matplotlib inline
plt.rcParams['figure.figsize'= (55)
plt.rcParams['font.size'= 15
plt.rcParams['font.family'= 'Malgun Gothic'
 
ratio = [final_2019.loc[final_2019['각색여부']==1]['공연코드'].count(), 
         final_2019.loc[final_2019['각색여부']==0]['공연코드'].count()]
labels = ['각색 연극''비각색 연극']
explode = [00.2]
colors = ['#F08080''#FFF8DC']
title_font = {'fontsize'15'fontweight''bold'}
 
plt.title('2019년도 각색 여부에 따른 연극 비율', fontdict=title_font)
plt.pie(ratio, labels=labels, autopct='%.1f%%', explode=explode, colors=colors, shadow=True)
plt.show()
cs

 

> EDA를 진행하면서 얻은 인사이트에 대해서 시각화를 해보았다.

 

> 2019년도 각색 여부에 따른 연극 비율에 대한 차트이고, 그 비율을 보면 각색하지 않은 연극의 비율이 압도적이라는 사실을 확인할 수 있었다. 

 


 

가설1 : 원작이 존재하는 연극이 그렇지 않은 연극에 비해 높은 흥행을 기록할 것이다.

 

> 이제 가설1에 대한 가설검정을 진행해 보자.

 

 

1
2
dramatic2019 = final_2019.loc[final_2019['각색여부']==1]
nondramatic2019 = final_2019.loc[final_2019['각색여부']==0]
cs

 

> 우리는 각색여부에 따라 각색(dramatic2019), 비각색(nondramatic2019)으로 데이터를 나누었다.

 

 

 

1
2
dramatic2019_aud = dramatic2019['관객수'].values
nondramatic2019_aud = nondramatic2019['관객수'].values
cs

 

> 그리곤 각색한 연극의 관객 수, 비각색 연극의 관객 수를 각각 다른 변수에 할당시켜 줬다.

 

 

 

1
2
group_dramatic2019_aud = dramatic2019_aud[dramatic2019_aud > 0]
group_nondramatic2019_aud = nondramatic2019_aud[nondramatic2019_aud > 0]
cs

 

> 그리곤 가설검정 해석에 방해가 되지 않도록 혹시 모를 음수값을 대비하였다. 

 

 

 

1
2
3
4
5
6
7
8
from scipy.stats import *
# 정규성 검정
print('원작을 각색한 연극 :',kstest(group_dramatic2019_aud, 'norm'))
print('원작을 각색하지 않은 연극 :',kstest(group_nondramatic2019_aud, 'norm'))
# 등분산성 검정
print('등분산성 검정 :',levene(group_dramatic2019_aud, group_nondramatic2019_aud))
# ttest
print('독립표본 T검정 :',ttest_ind(group_dramatic2019_aud, group_nondramatic2019_aud, equal_var=False))
cs

 

> 가설1의 특징을 살려 독립표본 T-검정을 사용하였고, 그에 따른 정규성 검정, 등분산성 검정을 진행한 후 t-test를 진행하였다.

 

 

> 정규성 검정

 

> 귀무가설 : 정규성을 만족한다.

> 대립가설 : 정규성을 만족하지 않는다.

 

 

> 등분산성 검정

 

> 귀무가설 : 등분산이 가정됨

> 대립가설 : 이분산이 가정됨

 

 

> 독립표본 T검정

 

> 귀무가설 : 각색한 연극의 관객 수와 비각색 연극의 관객수의 평균에는 차이가 없을 것이다.

> 대립가설 : 각색한 연극의 관객 수와 비각색 연극의 관객수의 평균에는 차이가 있을 것이다.

 

 

1
2
3
4
원작을 각색한 연극 : KstestResult(statistic=0.9513528046710726, pvalue=9.673547351549821e-195)
원작을 각색하지 않은 연극 : KstestResult(statistic=0.9598282652643644, pvalue=0.0)
등분산성 검정 : LeveneResult(statistic=11.261455527724259, pvalue=0.000814276275903258)
독립표본 T검정 : Ttest_indResult(statistic=1.5347759292769376, pvalue=0.12694454886747905)
cs

 

> 위 실행 결과에 따르면 두 집단 모두 정규성은 만족하였다.

> 하지만 등분산성을 만족하지 못하는 이분산이라는 결과가 도출되었다.

> 이 결과를 가지고 독립표본 T검정을 실시했을 때 유의 수준 0.05 하에서 귀무가설을 채택한다.

 

 

> 즉, 각색한 연극의 관객 수와 비각색 연극의 관객수의 평균에는 차이가 없다는 결론이다.

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
%matplotlib inline
plt.rcParams["figure.figsize"]=(55)
sns.set_style('whitegrid')
sns.set(font="Malgun Gothic"
        rc={"axes.unicode_minus":False},
        style='darkgrid')
g=sns.barplot(x='각색여부', y='관객수', palette='Set3',data=final_2019, ci=None)
g.set_xticklabels(['비각색','각색'], fontsize = 15)
g.set_title('2019년도 각색여부에 따른 평균 연극관객수',fontsize = 15, pad=30)
plt.xlabel('', fontsize = 15)
plt.ylabel('평균 관객수(명)', fontsize = 15)
cs

 

> 도출된 결론을 시각적으로 표현하기 위해 그래프를 그려보았다.

 

 

 

> 하지만 데이터에 기반하여 그래프를 그려본 결과 각색한 연극의 관객 수가 비각색 연극의 관객 수보다 압도적으로 많다는 것을 확인할 수 있다.

 

> 여기서 느낀 부분은 가설검정에서는 통계가 들어가는데 시각화한 차트에서는 그러한 부분이 결여되어 있기 때문에 해석의 차이가 도드라지지 않나 하는 것이다.

 

> 우리는 가설검정을 진행했기 때문에 시각화한 차트대신 통계적인 결과를 받아들이기로 했다.

 

 

 


 

> 지금까지는 2019년도 데이터만을 가지고 가설검정과 시각화를 진행했다.

> 위 과정을 2020년, 2021년, 2022년을 진행하고, 추가로 4개 연도를 병합하여 한 번 더 진행하였다.

 

 

> 하지만 거짓말처럼 결과는 모두 동일했고, 각색한 연극의 관객 수와 비각색 연극의 관객수의 평균에는 차이가 없다는 결론을 마주해야만 했다.