본문 바로가기
데이터 분석

[PySpark] 숙박업 분석 (2) - EDA

by 너굴맨_ 2022. 4. 13.

아래의 분석 과정은 숙박업 분석 (1)에 이어지는 내용이므로 아래 코드를 실행하는 경우 숙박업 분석(1)의 과정도 같이 진행해주시길 바랍니다.

 

※ 주의!! 

분석 데이터의 갱신일자의 다수는 2018년도로 2018년도 이후 분석 내용은 실제와 다를 수도 있습니다.

 

* 진행 과정

- toPandas를 통해 Pandas.DataFrame으로 변환

 

- 개방자치단체코드를 실제 지역명으로 변환

 

- 데이터 갱신일자 확인하기

 

- EDA

  • 영업 상태와 폐업 상태 건수를 알아보자
  • 운영기간의 분포 확인하기
  • 숙박업이 발달한 지역 확인하기
  • 면적 분포 확인하기
  • 년도 별 인허가 및 폐업 상황 확인하기
  • 변수 간의 상관관계 확인하기

 

- 변수 선택 및 변환

  • 불필요한 칼럼 제외 (번호, 사업장명, start_year, end_year)
  • 날짜형으로 데이터 변환
  • Label Encoding

- ToPandas 활용하여 Pandas.DataFrame 변환

toPandas를 사용하여 Pandas로 변환한 후 데이터가 가진 특징을 확인하자.
lodge_df = lodge.toPandas()

lodge_df.info()

lodge_df

- 개방자치단체코드를 실제 지역명으로 변환

개방자치단체코드를 실제 지역으로 변환 (강남구, 서초구 -> 서울특별시)
code = pd.read_csv("자치단체코드.csv", encoding='cp949')

code.head(10)

for i in range(len(code)):
    lodge_df['개방자치단체코드'][lodge_df['개방자치단체코드'] == code['자치단체코드'][i]] = code['지역구명'][i]
    
# 개방자치단체코드 -> 지역
lodge_df.rename(columns = {'개방자치단체코드':'지역'},inplace=True)

lodge_df

추가로 운영기간이라는 새로운 변수를 생성
temp1 = (lodge_df['폐업일자']/10000).round(0)
temp2 = (lodge_df['인허가일자']/10000).round(0)

# 운영기간 = 폐업일자 - 인허가일자 후 
lodge_df['운영기간'] = temp1 - temp2

lodge_df

- 데이터 갱신일자 확인하기

renewal_date = lodge_df['갱신일자'].value_counts()
renewal_date

위 데이터는 2018년 8월부터 2022년 3월까지의 정보를 포함하고 있으며 대다수의 데이터는 아직 2018년도에 머무르는 것을 확인하였다.

1. 영업 상태와 폐업상태 건수를 알아보자

상세영업상태명을 영업, 폐업, 휴업 3가지로 분류

※ 영업, 휴업을 제외한 자료는 모두 폐업으로 분류
 
lodge_df['상세영업상태명'][lodge_df['상세영업상태명'] == '영업중'] = '영업'
lodge_df['상세영업상태명'][(lodge_df['상세영업상태명'] != '영업') & (lodge_df['상세영업상태명'] != '휴업')] ='폐업'

current_status = lodge_df['상세영업상태명'].value_counts()

## 파이 차트로 나타내기
status_df = pd.DataFrame(current_status)
status_df = status_df.reset_index()
status_df.rename(columns = {'index' : '영업상태'}, inplace = True)

# pie 차트 형태로 나타내기
textprops = {"fontsize":13}
plt.figure(figsize=(10,10))
plt.pie(status_df['상세영업상태명'], labels=status_df['영업상태'],  autopct='%.1f%%', textprops= textprops)

 

2. 운영기간의 분포를 파악하자

운영기간이라는 새로운 변수를 아래와 같은 식을 통해 생성

운영기간(년도) = 폐업기간 - 인허가일자를 통해 운영기간을 구함

우선 인허가일자와 폐업기간 속 오류를 정정하는 작업 시행

 

# 우선 인허가일자와 폐업기간 속 오류를 정정하는 작업 시행
lodge_df['인허가일자'].sort_values()

lodge_df['폐업일자'].sort_values()

# 한국 정부 설립일 1948년 8월 15일 전에 허가가 된 자료들은 설립일로 변경
lodge_df['인허가일자'][lodge_df['인허가일자'] == 1931109] = 19931109
lodge_df['인허가일자'][lodge_df['인허가일자'] <= 19480815] = 19480815

# 폐업일자가 48년도 이전으로 나타난 경우 19480815로 변경
lodge_df['폐업일자'][lodge_df['폐업일자'] == 2014] = 20140000
lodge_df['폐업일자'][lodge_df['폐업일자'] == 199909] = 19990900
lodge_df['폐업일자'][lodge_df['폐업일자'] == 200003] = 20000300
lodge_df['폐업일자'][lodge_df['폐업일자'] == 200009] = 20000900
lodge_df['폐업일자'][lodge_df['폐업일자'] == 200204] = 20020400
lodge_df['폐업일자'][lodge_df['폐업일자'] == 2001123] = 20010123
lodge_df['폐업일자'][lodge_df['폐업일자'] <= 19480814] = 19480815
temp1 = (lodge_df['폐업일자']/10000).round(0)
temp2 = (lodge_df['인허가일자']/10000).round(0)

lodge_df['운영기간'] = temp1 - temp2

lodge_df['운영기간'].describe()

운영기간을 아래와 같이 구분하여 비율을 파악해보자

5년이하, 6~10년도, 11년-20년, 21년-30년, 31년-40년, 41년이상

period_1 = lodge_df['번호'][lodge_df['운영기간'] <=5].count()
period_2 = lodge_df['번호'][(lodge_df['운영기간'] >= 6) & (lodge_df['운영기간'] <=10)].count()
period_3 = lodge_df['번호'][(lodge_df['운영기간'] >= 11) & (lodge_df['운영기간'] <=20)].count()
period_4 = lodge_df['번호'][(lodge_df['운영기간'] >= 21) & (lodge_df['운영기간'] <=30)].count()
period_5 = lodge_df['번호'][(lodge_df['운영기간'] >= 31) & (lodge_df['운영기간'] <=40)].count()
period_6 = lodge_df['번호'][lodge_df['운영기간'] >= 41].count()
# 데이터프레임으로 만들고 Pie 차트 생성
period = pd.DataFrame({'운영기간':['5년이하','6~10년','11년~20년','21~30년','31~40년','41년 이상'],
                      'count':[period_1,period_2,period_3,period_4,period_5,period_6]})

period

# pie 차트 형태로 나타내기
colors = ['red', 'orange', 'yellow', 'lightgreen', 'skyblue','purple']
textprops = {"fontsize":15}

plt.figure(figsize=(12,12))
plt.pie(period['count'], labels=period['운영기간'], colors=colors, autopct='%.1f%%', textprops= textprops)

3. 숙박업이 발달한 지역 알아보기

# 0이거나 999로 표기된 자료는 알수없음으로 변경
lodge_df['지역'][lodge_df['지역'] == 0] = '알수없음'
lodge_df['지역'][lodge_df['지역'] == 999] = '알수없음'
lodge_count = lodge_df['지역'].value_counts()

lodge_count.head(30)

# 숙박업이 발달하지 못한 지역
lodge_count.tail(30)

4. 면적 분포 확인하기

시설면적에 대한 부분을 보면 자세한 조항이 없기 때문에 데이터 및 소재지라는 점을 봤을 때 대지면적으로 판단하는 것이 옳다고 판단하여 진행

출처: http://blog.hwenc.co.kr/477 (한화건설 공식 블로그)

size = lodge_df['면적']

size.sort_values(ascending=False)

Trouble Shooting

1. 면적 데이터 타입이 object를 int 형으로 변환

2. 일반적인 면적 분포를 파악하기 알고 싶었으나 사업장의 면적과 같은 부분은 자치구에서 중요하게 관리하는 부분이 아니라 아래와 같이 신뢰하기 힘든 데이터가 다수 포함. box plot을 통해 이상값은 0(알수없음)으로 변경
# 1. 데이터형 변환
lodge_df['면적'] = lodge_df['면적'].astype('float')
# 2. 면적의 최대값 설정하기
# boxplot 에서 이상값 경계치를 최대값으로 설정
# 0으로 설정된 부분은 중앙값으로 대체

find_max = lodge_df['면적']

# 중앙 값 확인
find_max.describe()

# 건물부지 최소크기는 60이므로 그 이하의 값은 중앙값으로 대체
# 98년도 이전 건물에는 해당 x -- 하지만 숙박업종 특성상 최소값을 지정하는 것이 옳다고 판단
find_max[find_max <= 60] = 335

# 5000이상의 값을 0으로 한뒤 boxplot으로 최대값 확인
find_max[find_max >= 5000] = 0

plt.boxplot(find_max)

위 BoxPlot을 통해 이상치 경계 1500을 Max 값으로 설정

lodge_df['면적'][lodge_df['면적'] >= 1500.1] = 0

lodge_df['면적'].describe()

# 면적 별로 나눠 분포 확인하기
bins = [-1,0,100,300,500,700,900,1100,1300,1500]
labels = ['알수없음','100미만', '100이상~300미만', '300이상~500미만', '500이상~700미만',
          '700이상~900미만','900이상~1100미만','1100이상~1300미만','1300이상~1500']
size_bins = pd.cut(lodge_df['면적'], bins, right=True, labels=labels)

size_bins

count_size = size_bins.value_counts(sort=False)

count_size

plt.figure(figsize=(20,8))            
bars = plt.bar(labels, count_size)

# access the bar attributes to place the text in the appropriate location
for bar in bars:
    yval = bar.get_height()
    plt.text(bar.get_x() + 0.3, yval + 0.2, yval)

대다수의 숙박업의 면적지는 300~500미만으로 평수로 나타내면 100평 ~ 150평 사이로 스타벅스 매장 평균 면적이 80임을 가만하면 1.2~2배 가까이의 면적을 갖고 있다.

 

5.년도별 인허가 및 폐업상황 그래프로 확인

1948년부터 2022년도까지의 허가 및 폐업 건수를 확인해보자

lodge_df['start_year'] = (lodge_df['인허가일자']/10000).astype('int')
lodge_df['end_year'] = (lodge_df['폐업일자']/10000).astype('int')
# 숙박업이 가장 많이 영업 시작된 년도
start = lodge_df['start_year'].value_counts()
start = start.sort_values(ascending=False)
start.head(10)

# 숙박업이 가장 많이 폐업한 년도
# 2022년도의 경우 현재 영업중인 데이터도 포함됨
# 2022년도 폐업한 업체의 수는 754
end = lodge_df['end_year'].value_counts()
end = end.sort_values(ascending=False)
end.head(10)

주의!! 실제 2022년도 폐업 건수가 아닌 현재 영업 중인 곳도 포함된 값으로 실제 2022년도 폐업 업체의 수는 3월 11일 기준 754곳으로 나타남

 

Trouble Shooting

년도별로 길이가 다른 부분이 발생 따라서 48년부터 22년까지의 74년간의 기록 중 누락되어있는 년도가 발생. 누락된 년도의 경우 0으로 채움
start = pd.DataFrame(start)
start['year'] = start.index

end = pd.DataFrame(end)
end['year'] = end.index
year = []

for i in range(1948,2023):
    year.append(i) 

year_df = pd.DataFrame(year)

year_df['year'] = year_df[0]
# start
start = pd.merge(year_df,start,how='outer', on='year')
start = start.fillna(0)

# end
end = pd.merge(year_df,end,how='outer', on='year')
end = end.fillna(0)
# 위 분석 1 과정을 통해 현재 운영중인 39135 업소를 2022에서 제외
end['end_year'][74] = (end['end_year'][74] - 39135)
plt.figure(figsize=(15,7))
plt.plot(year, start['start_year'], label="open")
plt.plot(year, end['end_year'], label='closed')
plt.legend(loc='upper right', fontsize=14)

위 그래프를 보면 2003년도에 제일 변화 폭이 컸으며 2015년부터 숙박업 업체 수가 증가하였지만 2018년부터 다시 큰 감소세가 나타났다. 갱신일자가 다수 데이터의 갱신일자가 2018년도에 머무른 것을 보면 실제 숙박업체의 감소세는 더 클것으로 전망된다.

2003년도에 숙박업 업체의 수가 늘어난 이유는 실제 업체 수의 증가가 아닌 1999년도 부터 통보제로 영업신고를 한 방식이 2003년부터 신고제로 영업 신고 방식이 변경되었기 때문에 변화 폭이 크게 상승한 것이다.

6. 변수 간 상관관계 파악하기

lodge_df.corr()

# 상관관계가 0.3 이상인 부분만 표현
corr = lodge_df.corr()
plt.subplots(figsize = (15, 12))
sns.heatmap(corr[(corr >= 0.3) | (corr <= -0.3)], cmap = 'viridis', vmax = 0.9, linewidth = 0.1, annot = True, annot_kws = {'size': 15}, square = True)

위 heatmap을 통해 2가지의 정보를 알 수 있는 점

1. 허가일자와 운영기간의 상관관계가 보이며 (허가일자가 최근년도에 가까울 수록 운영기간이 짧음)
2. 폐업일자와 인허가일자 간에 애매한 상관관계가 나타난다.
 

EDA

위 과정에서 진행한 것 말고 추가로 전처리 작업 진행

변수 선택 및 변환

1. 불필요한 칼럼 제외 (번호, 사업장명, start_year, end_year)
2. 날짜형으로 데이터 변환
3. Label Encoding

 

# 과정 2 진행 중 발생한 date 범위 오류값 수정
# 인허가일자
lodge_df['인허가일자'][lodge_df['인허가일자'] == 19970230] = 19970228
lodge_df['인허가일자'][lodge_df['인허가일자'] == 19750229] = 19750228
lodge_df['인허가일자'][lodge_df['인허가일자'] == 19940431] = 19940430
lodge_df['인허가일자'][lodge_df['인허가일자'] == 19840431] = 19840430

# 폐업일자
lodge_df['폐업일자'][lodge_df['폐업일자'] == 20020230] = 20020228
lodge_df['폐업일자'][lodge_df['폐업일자'] == 20020231] = 20020228
lodge_df['폐업일자'][lodge_df['폐업일자'] == 20140000] = 20140101
lodge_df['폐업일자'][lodge_df['폐업일자'] == 20000300] = 20000301
lodge_df['폐업일자'][lodge_df['폐업일자'] == 20020400] = 20020401
lodge_df['폐업일자'][lodge_df['폐업일자'] == 19990900] = 19990901
lodge_df['폐업일자'][lodge_df['폐업일자'] == 20000900] = 20000901
lodge_df['폐업일자'][lodge_df['폐업일자'] == 19970230] = 19970228
data = lodge_df

# 불필요한 칼럼 제외
data = data.drop(['번호','사업장명','start_year', 'end_year'], axis=1)
#-------- 날짜형으로 데이터 변환 ------------
# 약간 지저분한 방식으로 날짜형 데이터로 전환
# 1. int-> str 변환
# 2. str.slice 함수 사용하여 년도,월,일로 나눔
# 3. 나눠진 칼럼을 to_datetime으로 날짜형데이터로 변환
# 1~3 과정에서 발생한 임시 칼럼 삭제
def make_datetime(df,col):
    df[col] = df[col].astype('str')
    temp = df
    temp = pd.DataFrame(temp)
    temp['y'] = temp[col].str.slice(start=0, stop=4)
    temp['m'] = temp[col].str.slice(start=4, stop=6)
    temp['d'] = temp[col].str.slice(start=6, stop=8)
    
    temp[col] = temp['y']+"-"+temp['m']+"-"+temp['d']
    temp[col] = pd.to_datetime(temp[col])
    
    df['date'] = temp[col]
make_datetime(data,'인허가일자')
make_datetime(data,'폐업일자')

data = data.drop(['y','m','d','date'], axis=1)
# 본격적인 머신러닝을 하기 위해 0으로 지정한 값(null)을 중간값으로 값을 대체

data['운영기간'][data['운영기간'] ==0] = 17
data['면적'][data['면적'] == 0 ] = 335
data = data.sort_values(by="개방서비스명")

data.head(20)
알수없는 데이터는 ML에 좋지 못한 영향을 줄 수 있으므로 제외
data = data[12:]

data.to_csv("lodge_dataset.csv", encoding='cp949', index=None)

위 데이터 분석 과정에 대한 전반적인 내용은 아래 github 사이트에서 확인할 수 있습니다.

https://github.com/Han-Archives/Colab/blob/main/%5BPyspark%5D_%EC%88%99%EB%B0%95%EC%97%85_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EB%B6%84%EC%84%9D.ipynb

 

'데이터 분석' 카테고리의 다른 글

Matplotlib 사용법  (0) 2022.07.04
숙박업 분석 - (4) 요약 및 정리  (0) 2022.04.20
[PySpark] 숙박업 분석 - (1) 데이터 수집 및 전처리  (0) 2022.03.22
DataStudio 사용하기  (0) 2022.03.01
일별 출생건수 분석  (0) 2022.01.13

댓글