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

[AI 부트캠프] DAY 27 - 파이썬 EDA 7

by HOHHOH 2023. 8. 24.

[오늘의 일지]

파이썬 EDA 실시간 강의 - 공공데이터로 EDA 해보기, 타이타닉 데이터로 EDA 해보기

[상세 내용]

파이썬 EDA

공공데이터로 EDA 해보기

- 어제 사용했던 공공데이터 상권분석 자료를 이용해서 마저 남아 있던 주제의 분석을 마무리해 보겠습니다. 주제는 아래에 나와 있습니다.

  • 한식 음식점들이 많이 사용하는 단어 찾아보기

'많이 사용하는'이라는 말을 다르게 표현하자면 빈도분석이라고 하는데요. 빈도를 분석하기 위해서는 일단 각각 전국단위로 분리되어 있는 데이터를 하나로 묶어주는 것이 중요합니다. 이 과정은 어제 진행했었는데 다시 해보겠습니다. 여기서 데이터 파일을 불러올 때 glob()이라는 라이브러리가 유용하게 사용됩니다. glob()은 원하는 폴더 안에 존재하는 파일들 중 원하는 단어를 포함하는 파일들의 이름을 가진 모든 파일들의 이름을 리스트 형식으로 반환하는 역할을 합니다. 예시로 살펴보자면 glob() 안에 glob('./data/상가(상권) 정보_20230630/*.csv') 이런 형식으로 사용해 주면 폴더명 다음의 '/'이하에 '*'와 함께 원하는 단어를 포함한 즉 '.csv'를 포함한 모든 파일명을 리스트 형식으로 반환해 줍니다.

file_list = sorted(glob('./data/상가(상권)정보_20230630/*.csv'))
file_list
>>>
['./data/상가(상권)정보_20230630\\소상공인시장진흥공단_상가(상권)정보_강원_202306.csv',
 './data/상가(상권)정보_20230630\\소상공인시장진흥공단_상가(상권)정보_경기_202306.csv',
 './data/상가(상권)정보_20230630\\소상공인시장진흥공단_상가(상권)정보_경남_202306.csv',
 './data/상가(상권)정보_20230630\\소상공인시장진흥공단_상가(상권)정보_경북_202306.csv',
 './data/상가(상권)정보_20230630\\소상공인시장진흥공단_상가(상권)정보_광주_202306.csv',
 './data/상가(상권)정보_20230630\\소상공인시장진흥공단_상가(상권)정보_대구_202306.csv',
 './data/상가(상권)정보_20230630\\소상공인시장진흥공단_상가(상권)정보_대전_202306.csv',
 './data/상가(상권)정보_20230630\\소상공인시장진흥공단_상가(상권)정보_부산_202306.csv',
 './data/상가(상권)정보_20230630\\소상공인시장진흥공단_상가(상권)정보_서울_202306.csv',
 './data/상가(상권)정보_20230630\\소상공인시장진흥공단_상가(상권)정보_세종_202306.csv',
 './data/상가(상권)정보_20230630\\소상공인시장진흥공단_상가(상권)정보_울산_202306.csv',
 './data/상가(상권)정보_20230630\\소상공인시장진흥공단_상가(상권)정보_인천_202306.csv',
 './data/상가(상권)정보_20230630\\소상공인시장진흥공단_상가(상권)정보_전남_202306.csv',
 './data/상가(상권)정보_20230630\\소상공인시장진흥공단_상가(상권)정보_전북_202306.csv',
 './data/상가(상권)정보_20230630\\소상공인시장진흥공단_상가(상권)정보_제주_202306.csv',
 './data/상가(상권)정보_20230630\\소상공인시장진흥공단_상가(상권)정보_충남_202306.csv',
 './data/상가(상권)정보_20230630\\소상공인시장진흥공단_상가(상권)정보_충북_202306.csv']

 

- 그럼 이제 모든 파일명이 담긴 리스트를 이용해서 나눠져 있는 전국 데이터를 하나로 만드는 과정을 진행해 보겠습니다. for문을 이용해서 전국 데이터 파일 리스트를 판다스의 csv 읽기 함수를 이용해서 읽어낸 다음 판다스의 concat함수를 이용해서 데이터를 하나씩 붙여주면 마무리됩니다.

# 데이터들을 불러와봅시다.
# 함수의 파라미터로 파일 이름 규칙을 주면, 규칙에 해당하는 파일 이름을 모두 가져오는 함수.
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
>>>
	상가업소번호	상호명	지점명	상권업종대분류코드	상권업종대분류명	상권업종중분류코드	상권업종중분류명	상권업종소분류코드	상권업종소분류명	표준산업분류코드	...	건물관리번호	건물명	도로명주소	구우편번호	신우편번호	동정보	층정보	호정보	경도	위도
0	MA0101202210A0084547	금강산노래광장	NaN	I2	음식	I211	주점	I21101	일반 유흥 주점	I56211	...	4217010300007470000000086	파크장	강원특별자치도 동해시 송정로 11	240806	25789	NaN	지	NaN	129.127525	37.495265
1	MA010120220805430826	에이치속눈썹수강아카데미	NaN	S2	수리·개인	S207	이용·미용	S20702	피부 관리실	S96113	...	4211039021110620001000001	NaN	강원특별자치도 춘천시 동내면 외솔길19번길 80-36	200883	24401	NaN	NaN	NaN	127.758764	37.857831
2	MA010120220805430903	엔젤	NaN	I2	음식	I201	한식	I20101	백반/한정식	I55109	...	4277032022103660000008290	NaN	강원특별자치도 정선군 남면 민둥산로 175-13	233837	26148	NaN	NaN	NaN	128.792089	37.259788
3	MA010120220805430941	누베헤어	NaN	S2	수리·개인	S207	이용·미용	S20701	미용실	S96112	...	4211012500100440010000008	춘천파크자이	강원특별자치도 춘천시 스포츠타운길 458	200200	24472	NaN	3	NaN	127.707653	37.867744
4	MA010120220805430946	공차	NaN	I2	음식	I212	비알코올	I21201	카페	I56229	...	4213033023113500001000001	NaN	강원특별자치도 원주시 지정면 신지정로 211	220821	26354	NaN	NaN	NaN	127.872713	37.374189
...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...
81718	MA0101202303A0020503	꽃개	NaN	G2	소매	G220	애완동물·용품 소매	G22001	애완동물/애완용품 소매업	G47852	...	4377033021106020004000001	NaN	충청북도 음성군 맹동면 덕금로 236	369811	27733	NaN	NaN	NaN	127.546988	36.925111
81719	MA0101202303A0014518	만두를빚다	NaN	I2	음식	I210	기타 간이	I21007	김밥/만두/분식	I56111	...	4311110300100960017052823	NaN	충청북도 청주시 상당구 중앙로 28-1	360012	28543	NaN	1	NaN	127.488871	36.639523
81720	MA0101202303A0107065	골목식당	NaN	I2	음식	I201	한식	I20101	백반/한정식	I56111	...	4375025024104780038023581	NaN	충청북도 진천군 진천읍 중앙서로 10-1	365807	27831	NaN	NaN	NaN	127.442060	36.859096
81721	MA0101202303A0033503	씨유옥천청산점	NaN	G2	소매	G204	종합 소매	G20405	편의점	G47122	...	4373035021100850007007997	NaN	충청북도 옥천군 청산면 지전1길 3	373874	29013	NaN	2	NaN	127.792482	36.344138
81722	MA0101202303A0033505	카페지아니	NaN	I2	음식	I212	비알코올	I21201	카페	I56221	...	4374525028101720000006486	NaN	충청북도 증평군 증평읍 문화로 62	368904	27933	NaN	NaN	NaN	127.590042	36.784990
2417759 rows × 39 columns

 

- courpus : 이제 합쳐진 데이터에서 주제였던 '한식'을 키워드로 가져와야 합니다. 한식'을 가져오는 것은 mask처리해서 loc함수를 이용하면 어렵지 않게 가져올 수 있습니다. 상호명은 그냥 lod함수로 가져오면 됩니다. 이렇게 상호명을 추출하는 것을 일종에 corpus라고 하는데요. corpus라는 단어는 특정한 목적을 가지고 언어의 표본을 추출한 집합이라는 의미를 가지고 있습니다.

# corpus
corpus = data.loc[data['상권업종중분류명'] == '한식', '상호명']
corpus
>>>
2            엔젤
10         태능갈비
12        박차닭갈비
14        남경막국수
27          먹자골
          ...  
81700    다정정육식당
81710      충남순대
81711    장어92번지
81717      일등식당
81720      골목식당
Name: 상호명, Length: 322709, dtype: object

 

- tokenization : 사실  tokenization를 하기 전에 text cleaning이라고 하는 것을 실행해야 하는데 정확하게 단어를 뽑아내려면 문장을 정규 표현식을 사용해서 일일이 불용어를 제거하는 등 해야 하는 작업이 생각보다 오래 걸려서 생략하고 그냥 라이브러리를 이용하는 tokenization라는 형태소 분석기라는 의미를 가지고 있는 이것을 사용하게 되었습니다. 보통 여러 가지 라이브러리를 사용할 수 있지만 파이썬에서는 pecab을 사용하였습니다. 사용 예시로는 위에서도 나와 있듯이 상호명에 나오는 음식을 분리시켜서 빈도수를 알아보기 위함입니다. 그럼 pecab의 예시를 알아보겠습니다.

# pecab : Mecab의 python Version
from pecab import PeCab

pecab = PeCab()
# 모든 단위를 짤라주는 것 뿐만 아니라 품사까지 알려주는 함수 pos
pecab.pos('아버지가방에들어가신다.')
>>>
[('아버지', 'NNG'),
 ('가', 'JKS'),
 ('방', 'NNG'),
 ('에', 'JKB'),
 ('들어가', 'VV'),
 ('신다', 'EP+EF'),
 ('.', 'SF')]
 
 # 모든 단위를 짤라주는 함수 morphs
 pecab.morphs('아버지가방에들어가신다.')
 >>>
 ['아버지', '가', '방', '에', '들어가', '신다', '.']
 
 # 단위로 짜르고 명사만을 분리해서 출력하는 nouns
 pecab.nouns('아버지가방에들어가신다.')
 >>>
 ['아버지', '방']

 

- 이제 상호명을 분리해서 저장한 corpus를 tokenization 해 보겠습니다. 생각보다 시간이 오래 걸렸습니다.

tokenized_corpus = []

for doc in tqdm(corpus):
    tokenized_corpus.append(pecab.nouns(doc))
tokenized_corpus
>>>
[['엔젤'],
 ['갈비'],
 ['닭갈비'],
 ['남경', '막국수'],
 ['골'],
 ['아리랑', '산촌', '식당'],
 ['인구', '시장'],
 ['밥집'],
 ['홍천', '해물', '찜'],
 ['원조', '남원주'],
 ['이모', '한식'],
 ['영랑', '해변', '장어', '꿈'],
 ['강남', '교자'],
 ['황토', '집'],
 ['돼지'],
 ...]
 
# 근데 위에 리스트는 리스트 안에 또 리스트가 있는 구조라 
# 안에 리스트를 제거하는 과정을 거쳐야 Counter 모듈을 사용할 수 있습니다.
total_tokens = []
for tokens in tqdm(tokenized_corpus):
    total_tokens = total_tokens + tokens   # concatenation
total_tokens
>>>
['엔젤',
 '갈비',
 '닭갈비',
 '남경',
 '막국수',
 '골',
 '아리랑',
 '산촌',
 '식당',
 '인구',
 '시장',
 '밥집',
 '홍천',
 '해물',
 '찜',
 '원조',
 '남원주',
 '이모',
 '한식',
 '영랑',
 '해변',
 '장어',
 '꿈',
 '강남',
 '교자',
 '황토',
 '집',
 '돼지',
 ...]

 

- modeling : 리스트화된 키워드들을 숫자와 함께 정리할 수 있는데 collections 라이브러리의 Counter 모듈을 사용하면 됩니다.

# modeling
from collections import Counter
counter = Counter(total_tokens)
counter.most_common(30)
>>>
[('식당', 32712),
 ('집', 12613),
 ('족발', 7024),
 ('점', 6986),
 ('칼국수', 6333),
 ('갈비', 5983),
 ('찜', 5945),
 ('횟집', 5370),
 ('푸드', 5214),
 ('곱창', 4833),
 ('삼', 4778),
 ('국밥', 4758),
 ('돈', 4268),
 ('밥', 4171),
 ('고기', 4148),
 ('돼지', 3898),
 ('닭', 3741),
 ('국수', 3608),
 ('감자탕', 3501),
 ('밥상', 3497),
 ('구이', 3435),
 ('해장국', 3435),
 ('순대', 3353),
 ('추어탕', 2933),
 ('대국', 2849),
 ('왕', 2830),
 ('숯불', 2756),
 ('닭갈비', 2750),
 ('골', 2740),
 ('한우', 2687)]

 

- 마지막으로 wordcloud 라이브러리를 이용해서 키워드의 개수 별로 단어의 크기를 나타내 주는 지표를 완성하면 끝나게 됩니다.

import matplotlib
import matplotlib.font_manager as fm

#plt.rc('font',family='AppleGothic')
# font_location = '/System/Library/Fonts/AppleSDGothicNeo.ttc'
font_location = 'C:/Windows/Fonts/Malgun.ttf' # For Windows
font_name = fm.FontProperties(fname=font_location).get_name()
print(font_name)
matplotlib.rc('font', family=font_name)

from wordcloud import WordCloud

wc = WordCloud(font_path=font_location,       # 사용하는 글꼴의 경로
               max_words=100,                 # 최대 몇개의 단어를 사용할지 (빈도순)
               width=1920,                    # 가로 길이
               height=1080,                   # 세로 길이 
               random_state=42,               # for reproducing  
               background_color='white',      # 배경 색, 기본이 검정.  
               colormap='viridis'             # color palette 
              ).generate_from_frequencies(counter)
plt.axis('off')
plt.savefig('./wordcloud.png')
plt.imshow(wc)

한식 음식점들이 많이 사용하는 단어의 wordcloud

 

 타이타닉 데이터로 EDA 해보기

- 타이타닉 자료는 지난 수업에도 많이 사용했는데 오늘의 주제는 아래와 같습니다.

  • 타이타닉 생존자와 상관관계가 높은 요소 찾기

- 타이타닉 데이터를 불러와서 결측치가 있는지 조사합니다.(원래 데이터 분석을 할 때 이행해야 하는 디폴트값과 같은 과정이라고 설명해 주셨습니다.)

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# train.csv 파일 불러오기
titanic = pd.read_csv('./data/titanic/train.csv')
titanic

# 결측치가 존재하는지
titanic[titanic.isnull().any(axis=1)]

 

- 이번 상관관계를 알아보는 과정에서는 결측치를 크게 신경 쓰지 않았던 거 같습니다. 그런 뒤 dtype을 이용해서 object인 칼럼을 찾았습니다. 그리고 생존 비율을 알아봤습니다.(여기까지가 디폴트값이라고 하셨습니다. 총 정리하자면 첫 번째 결측지가 존재하는지 파악하기, 두 번째 object 타입을 가지는 칼럼이 존재하는지, 마지막으로 타깃의 값의 분배비율을 알아보는 것 까지가 데이터 분석의 디폴드값처럼 이행되는 초기 단계라고 하셨습니다.)

# dtype이 object인 column이 있는지
titanic.columns[titanic.dtypes == 'object']
>>>
Index(['Name', 'Sex', 'Ticket', 'Cabin', 'Embarked'], dtype='object')

# target value의  distribution이 어떻게 되는지
titanic.Survived.value_counts()
sns.countplot(data=titanic, x='Survived')
>>>

타이타닉 생존비율 1이 생존

- 상관계수를 corr함수로 구하고 heatmap 만들기 (생존자와 관련이 깊은 칼럼은 'Pclass'와 'Fare'으로 좌석의 클래스와 요금인데요. 역시 생존율과 경제적 지위가 비교적 관련이 높았던 것으로 판단이 됩니다. )

# correlation matrix heatmap
corr = titanic.corr()
corr
>>>
		PassengerId	Survived	Pclass		Age		SibSp		Parch		Fare
PassengerId	1.000000	-0.005007	-0.035144	0.036847	-0.057527	-0.001652	0.012658
Survived	-0.005007	1.000000	-0.338481	-0.077221	-0.035322	0.081629	0.257307
Pclass		-0.035144	-0.338481	1.000000	-0.369226	0.083081	0.018443	-0.549500
Age		0.036847	-0.077221	-0.369226	1.000000	-0.308247	-0.189119	0.096067
SibSp		-0.057527	-0.035322	0.083081	-0.308247	1.000000	0.414838	0.159651
Parch		-0.001652	0.081629	0.018443	-0.189119	0.414838	1.000000	0.216225
Fare		0.012658	0.257307	-0.549500	0.096067	0.159651	0.216225	1.000000

sns.heatmap(data=corr, annot=True, fmt='.3f', cmap='Reds')

heatmap으로 생존율관 관련된 요소 찾기

 

[마무리]

 오늘도 어제에 이어서 여러 가지 EDA를 실행했습니다. 오늘은 비교적 많은 양의 데이터를 하나로 전처리하는 과정이 있었습니다. 그 과정에서 여러 가지 느낀 것들이 있습니다. 많은 양의 데이터를 사용하기 위해서는 컴퓨터의 사양도 중요하다는 것과 생각보다 데이터를 다루는 것이 오래 걸리는 작업이라는 것을 느꼈습니다. 머신러닝 과정도 시간이 꽤 걸리는 과정들이 많다고 들었는데 벌써부터 걱정되고 기대도 되는 것 같습니다.

반응형

댓글