본문 바로가기
AI/데이터 사이언스

[AI 부트캠프] DAY 26 - 파이썬 EDA 6

by HOHHOH 2023. 8. 23.

[오늘의 일지]

파이썬 EDA 실시간 강의 - Seaborn 복습, 공공데이터로 EDA 해보기

[상세 내용]

파이썬 EDA

Seaborn 복습

- 오늘 복습은 lineplot, scatterplot, pairplot, heatmap까지 마무리를 하였습니다.  lineplot과 scatterplot은 hue 파라미터를 첨가해서 그래프를 분석해 보면 두 plot의 경향성은 hue에서 설정한 칼럼의 데이터 별로 보면 각각의 분포를 파악할 수 있다는 점에서 비슷한 부분을 가지고 있습니다. 

# penguin 데이터에 lineplot을 출력합니다.
sns.lineplot(data=data, x='body_mass_g', y='flipper_length_mm', errorbar=None, hue='species',palette='viridis')

각 종별로 x,y축의 경향성을 분석할 수 있다.

 

- pairplot 각각의 scatterplot, FacetGrid, kdeplot을 이용하여 feature 간의 관계를 확인할 수 있다는 점에서 유용합니다. 너무 많은 칼럼을 가지고 있는 데이터라면 보기 힘들 수 있다는 단점이 있습니다.

# penguin 데이터에 pairplot을 출력합니다.
sns.pairplot(data=data, hue='species')

수치 데이터는 모두 비교한 그래프

 

- heatmap은 우선 상관관계를 알아야 값을 구할 수 있는 서로 간의 연관성이 중요한 그래프입니다. 상관계수는 값을 1을 기준으로 얼마나 가까운지 나타낼 수 있는 지표입니다. 우선 상관계수를 corr() 함수를 이용해서 구해보고 히트맵을 만들어 보겠습니다. 히트맵은 색깔별로 상관관계를 표현해 주기 때문에 보기에도 매우 유용합니다.

# 각 feature간 상관관계를 파악하기 위해 Correlation matrix를 만듭니다.
data.corr()
>>>

			bill_length_mm	bill_depth_mm	flipper_length_mm	body_mass_g
bill_length_mm			1.000000	-0.228626	0.653096	0.589451
bill_depth_mm			-0.228626	1.000000	-0.577792	-0.472016
flipper_length_mm		0.653096	-0.577792	1.000000	0.872979
body_mass_g			0.589451	-0.472016	0.872979	1.000000

 

# penguin 데이터에 heatmap을 출력합니다.
sns.heatmap(data=data.corr(), annot=True, fmt='.3f',cmap='Blues')

 

눈으로만 봐도 알 수 있는 상관관계

 

공공데이터로 EDA 해보기

- 이번에 사용하게 될 공공데이터는 공공데이터 포탈이라는 사이트에서 공개한 전국의 영업 중인 상가 정보입니다. 이 데이터는 시기별로 계속해서 업데이트된다는 특징을 가지고 있어서 연습하기에도 좋은 거 같습니다. 그럼 순서대로 EDA를 시작해 보겠습니다. 

 

소상공인시장진흥공단_상가(상권)정보_20221231

영업 중인 전국 상가업소 데이터를 제공합니다.<br/>(상호명, 업종코드, 업종명, 지번주소, 도로명주소, 경도, 위도 등)<br/><br/>[데이터 변경 안내] <br/><br/>1. 상권업종분류 : 표준산업분류 기반 업

www.data.go.kr

 

- 분석하고 싶은 주제 정하기 : 저는 수업시간에 강사님이 몇 가지 주제를 정해 주셨습니다. 주제는 다음과 같습니다.

  • 한식 / 일식 / 중식 음식점 비율 찾기
  • 각 지역별 음식점 비율 계산해 보기

 

- 원하는 데이터를 찾기 위한 전처리 과정 : 원하는 데이터를 찾기에 앞서서 일단 전국 단위로 분리되어 있는 데이터를 모두 하나의 데이터로 합치는 작업을 했습니다. (칼럼의 이름에 대한 정보만 보기 위해서 data.info를 활용합니다.)

# 데이터들을 불러와봅시다.
# 함수의 파라미터로 파일 이름 규칙을 주면, 규칙에 해당하는 파일 이름을 모두 가져오는 함수.
file_list = sorted(glob('./data/상가(상권)정보_20230630/*.csv'))
file_list

data = pd.DataFrame()

for file in tqdm(file_list):
    temp = pd.read_csv(file)
    data = pd.concat([data,temp], axis=0)
data
>>>
상가업소번호	상호명	지점명	상권업종대분류코드	상권업종대분류명	상권업종중분류코드	상권업종중분류명	...
2417759 rows × 39 columns

# 데이터가 너무 많아서 랜덤 샘플로 가져올 수 있습니다.
# df = data[:10000]
df = data.sample(n=10000, random_state=42)
df
>>>
10000 rows × 39 columns
data.info(memory_usage='deep')
>>>
<class 'pandas.core.frame.DataFrame'>
Int64Index: 2417759 entries, 0 to 81722
Data columns (total 39 columns):
 #   Column     Dtype  
---  ------     -----  
 0   상가업소번호     object 
 1   상호명        object 
 2   지점명        object 
 3   상권업종대분류코드  object 
 4   상권업종대분류명   object 
 5   상권업종중분류코드  object 
 6   상권업종중분류명   object 
 7   상권업종소분류코드  object 
 8   상권업종소분류명   object 
 9   표준산업분류코드   object 
 10  표준산업분류명    object 
 11  시도코드       int64  
 12  시도명        object 
 13  시군구코드      int64  
 14  시군구명       object 
 15  행정동코드      int64  
 16  행정동명       object 
 17  법정동코드      int64  
 18  법정동명       object 
 19  지번코드       int64  
 20  대지구분코드     int64  
 21  대지구분명      object 
 22  지번본번지      float64
 23  지번부번지      float64
 24  지번주소       object 
 25  도로명코드      int64  
 26  도로명        object 
 27  건물본번지      float64
 28  건물부번지      float64
 29  건물관리번호     object 
 30  건물명        object 
 31  도로명주소      object 
 32  구우편번호      int64  
 33  신우편번호      int64  
 34  동정보        float64
 35  층정보        object 
 36  호정보        float64
 37  경도         float64
 38  위도         float64
dtypes: float64(8), int64(9), object(22)
memory usage: 4.4 GB

 

- tip: 방대한 양의 데이터를 가져올 때는 로딩이 길어지는데 과정을 막대 수치로 볼 수 있는 tqdm이라는 라이브러리가 있습니다.

from tqdm.auto import tqdm # progress bar

for file in tqdm(file_list):
    temp = pd.read_csv(file)
    data = pd.concat([data,temp], axis=0)
>>>
# 이런식으로 보여줍니다. 사용법은 for문에서 in에 해당하는 데이터 파일에 넣어줍니다.
100%|██████████████████████████████████████████████████████████████████████████████████| 17/17 [00:23<00:00,  1.36s/it]

 

- 줄어든 데이터를 이용해서 칼럼을 분석합니다.(주제가 음식점이니 음식점을 찾을 수 있는 칼럼과 지역별 칼럼을 찾습니다.) '상권업종중분류명'이라는 칼럼에 '한식'이라는 데이터를 찾았습니다. 시도명이라는 칼럼에서도 지역단위를 알게 되었습니다.

df.iloc[:,1:11]
>>>
	상호명	지점명	상권업종대분류코드	상권업종대분류명	상권업종중분류코드	상권업종중분류명	상권업종소분류코드	상권업종소분류명	표준산업분류코드	표준산업분류명
101226	라이풀	NaN	I2	음식	I204	서양식	I20401	경양식	I56123	서양식 음식점업
41200	토리비어	NaN	I2	음식	I211	주점	I21104	요리 주점	I56219	기타 주점업
146236	삼삼공	NaN	I2	음식	I201	한식	I20101	백반/한정식	I56111	한식 일반 음식점업
105044	힐링아로마	NaN	G2	소매	G215	의약·화장품 소매	G21503	화장품 소매업	G47813	화장품, 비누 및 방향제 소매업
24645	삼한직업소개소	NaN	N1	시설관리·임대	N104	고용 알선	N10401	고용 알선업	N75110	고용 알선업
10000 rows × 10 columns
df.iloc[:,11:15]
>>>
	시도코드	시도명	시군구코드	시군구명
101226	48	경상남도	48890	합천군
41200	29	광주광역시	29140	서구
146236	41	경기도	41171	안양시 만안구
105044	27	대구광역시	27290	달서구
24645	44	충청남도	44131	천안시 동남구
...	...	...	...	...
33418	46	전라남도	46130	여수시
435394	11	서울특별시	11530	구로구
52418	44	충청남도	44131	천안시 동남구
221968	41	경기도	41271	안산시 상록구
39987	48	경상남도	48740	창녕군
10000 rows × 4 columns

 

- 그럼 이제 원하는 칼럼으로만 다시 전체 데이터를 분리해서 가져올 수 있습니다.

data1 = data[['상호명', '상권업종대분류명', '상권업종중분류명', '시도명']]
data1
>>>
	상호명	상권업종대분류명	상권업종중분류명	시도명
0	금강산노래광장	음식	주점	강원특별자치도
1	에이치속눈썹수강아카데미	수리·개인	이용·미용	강원특별자치도
2	엔젤	음식	한식	강원특별자치도
3	누베헤어	수리·개인	이용·미용	강원특별자치도
4	공차	음식	비알코올	강원특별자치도
...	...	...	...	...
81718	꽃개	소매	애완동물·용품 소매	충청북도
81719	만두를빚다	음식	기타 간이	충청북도
81720	골목식당	음식	한식	충청북도
81721	씨유옥천청산점	소매	종합 소매	충청북도
81722	카페지아니	음식	비알코올	충청북도
2417759 rows × 4 columns

 

- 한식 / 일식 / 중식 음식점 비율 찾기 : 원하는 데이터인 전체 음식 업종 중에 한식, 일식, 중식에 대한 데이터의 비율을 구할 수 있게 되었습니다.

한식 = round(len(data1.loc[data1['상권업종중분류명'] == '한식'])/len(data.loc[data['상권업종대분류명'] == '음식'])*100,3)
중식 = round(len(data1.loc[data1['상권업종중분류명'] == '중식'])/len(data.loc[data['상권업종대분류명'] == '음식'])*100,3)
일식 = round(len(data1.loc[data1['상권업종중분류명'] == '일식'])/len(data.loc[data['상권업종대분류명'] == '음식'])*100,3)

print(f'한식 분류 : {한식}%')
print(f'일식 분류 : {일식}%')
print(f'중식 분류 : {중식}%')
>>>
한식 분류 : 40.835%
일식 분류 : 2.632%
중식 분류 : 3.752%

 

- 각 지역별 음식점 비율 계산해 보기 : unique() 함수를 사용해서 시도명 칼럼에 있는 모든 object를 가져올 수 있습니다. 그런 다음 for문을 이용해서 시도명에 있는 각 시도별로 sido라는 이름 안에 분리시킵니다. 그리고 시도별로 '상권업종중분류명'칼럼의 한식과 '상권업종대분류명'의 '음식'을 가져와서 비율을 구해주면 됩니다.

시도명 = data['시도명'].unique()
시도명
>>>
array(['강원특별자치도', '경기도', '경상남도', '경상북도', '광주광역시', '대구광역시', '대전광역시',
       '부산광역시', '서울특별시', '세종특별자치시', '울산광역시', '인천광역시', '전라남도', '전라북도',
       '제주특별자치도', '충청남도', '충청북도'], dtype=object)
       
# 각 지역별 음식점(한식) 비율 계산
for 시도 in 시도명:
    sido = data.loc[data['시도명'] == 시도]
    sido_hansik = sido.loc[sido['상권업종중분류명'] == '한식']
    sido_food = sido.loc[sido['상권업종대분류명'] == '음식']
    print((f"{시도} 한식 비율: {len(sido_hansik)/len(sido_food)*100:.2f}%"))
>>>
강원특별자치도 한식 비율: 48.87%
경기도 한식 비율: 39.07%
경상남도 한식 비율: 44.54%
경상북도 한식 비율: 46.53%
광주광역시 한식 비율: 37.58%
대구광역시 한식 비율: 39.69%
대전광역시 한식 비율: 40.63%
부산광역시 한식 비율: 39.08%
서울특별시 한식 비율: 34.46%
세종특별자치시 한식 비율: 39.84%
울산광역시 한식 비율: 43.07%
인천광역시 한식 비율: 39.03%
전라남도 한식 비율: 45.35%
전라북도 한식 비율: 42.93%
제주특별자치도 한식 비율: 42.93%
충청남도 한식 비율: 45.98%
충청북도 한식 비율: 45.68%

 

[마무리]

 오늘은 본격적으로 EDA를 실행해 보는 과정을 진행하기 시작했습니다. EDA라는 것이 어떠한 원하는 주제를 정해서 데이터를 세분화한다는 점에서 제가 생각하기에는 데이터 분석 분야에서 꼭 필요한 파트라는 것을 느꼈습니다. 그렇다고 해서 AI 분야랑 무관하다는 것도 아니라고 강사님이 강조하셨기 때문에 전반적으로 매우 유익한 과정이라고 생각하고 있습니다. 유익한 과정인 만큼 열심히 학습을 따라가도록 노력해야겠습니다.

반응형

댓글