카테고리 없음

14. 한글 text 데이터 분석 및 전처리

nananakh 2023. 7. 10. 15:13

우리가 영어로 된 text data를 전처리 하고자 할때는 nltk라는 라이브러리를 사용했다.

그런데 nitk는 한국어를 지원하지 않는다. 그래서 한글용 라이브러리인 Konlpy를 사용한다.

이건 좋긴 한데, 설치가 매우 까다롭다.

from konlpy.tag import Okt

tokenizer = Okt()
tokens = tokenizer.pos("아버지 가방에 들어가신다.", norm=True, stem=True)
print(tokens)
[('아버지', 'Noun'), ('가방', 'Noun'), ('에', 'Josa'), ('들어가다', 'Verb'), ('.', 'Punctuation')]

테스트를 해보면 다음과 같다. 

nltk는 nltk.word_tokenizer(문장 입력) >> nltk.pos_tag(token된 문장)을 했는데,

Konlpy는 tokenizer와 pos_tag 작업을 동시에 진행시켜준다.

 

이때, norm과 stem이 활성화 되어있다.

 

norm == 정규화(normalization)
'한국어를 처리하는 예시입니닼ㅋㅋㅋ '-> '한국어를 처리하는 예시입니다ㅋㅋ'
텍스트 데이터를 정갈하게 다듬어준다.

 

stem == 어근화(stemming)

식물의 줄기라는 뜻 / 사전형 단어로 바꿔줌. / lemma~과 같은 기능
한국어를 처리하는 예시입니다 ㅋㅋ -> 한국어Noun, 를Josa, 처리Noun, 하다Verb, 예시Noun, 이다Adjective, ㅋㅋKoreanParticle

 

이제 불용어(한글자로 된 단어와 원하지 않은 단어)를 제거한 뒤, 각 단어의 출현 빈도수를 세주는 작업을 해주자.

raw_pos_tagged
[ ('인천', 'Noun'),
 ('테크노', 'Noun'),
 ('파크', 'Noun'),
 ('로고', 'Noun'),
 ('.', 'Punctuation'),
 ('(', 'Punctuation'),
 ('이미지', 'Noun'),
 ('=', 'Punctuation'),
 ('인천', 'Noun'),
 ('테크노', 'Noun')]
word = []

stopwords = [',', '을', '를', ~]
for i in raw_pos_tagged:
	if i[1] not in ["Josa", "Eomi", "Punctuation", "Foreign"]:
    	if (len(i[0])!=1) & (i[0] not in stopwords):
        	word.append(i[0])
['인천',
 '뉴시스',
 '루비',
 '기자',
 '인천',
 '테크노']

이제 출현 횟수를 세주는 방법은 두가지가 있다.

word_count = {}

for i in word:
	if i not in word_count:
    	word_count[i] = 1
    else:
    	word_count[i] +=1
from collections import Counter

word_count = Counter(word)
word_dic = dict(word_count)
word_dic
{'인천': 15,
 '뉴시스': 13,
 '루비': 2,
 '기자': 20,
 '테크노': 3,
 '파크': 3,
 '로고': 1]

이것을 출현빈도 순으로 정렬을 해준다.

word_sort = sorted(word_dic.items(), key = lambda x : x[1], reverse = True)

이때, word_dic.items()는 dict값을 tuple로 꺼내서 출현 횟수를 꺼낼 수 있게 해주는 것이다.

 word_dic.items()[1] >> 출현 횟수만 뽑아진다.

dict_items([('인천', 15), ('뉴시스', 13), ('루비', 2), ('기자', 20), ('테크노', 3), ('파크', 3), ('로고', 1),

상위 50개의 단어를 출력하는 코드는 다음과 같다.

for i in word_sort[:50]:
	print(i[0](i[1]))
데이터(538) 분석(252) 서비스(154) 빅데이터(115) 활용(102) 기업(96) 기술(93) 개발(89)

 

단어 등장 빈도를 시각화 해보자.

import nltk
import matplotlib
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc

font_name = matplotlib.font_manager.FontProperties(fname="C:/Windows/Fonts/malgun.ttf").get_name() # NanumGothic.otf
matplotlib.rc('font', family=font_name)

불용어를 제거한 단어 사전을 가져오자.

word

['인천', '뉴시스', '루비', '기자', '인천', '테크노', '파크', '로고' ~]
word_count = nltk.Text(word)
plt.figure(figsize = (15, 5))
word_count.plot(50)

nltk.Text 함수가 자동으로 단어 갯수를 세주고, 정렬까지 해준다.

plot(50)은 상위 50개의 단어로 그래프를 그려준다는 뜻이다.

이때, 줄그래프 말고 막대 그래프로 그릴수 있다.

막대그래프는 바로 그릴 수 없어서 nltk의 FreqDist 함수를 거친 뒤, DataFrame에 데이터를 담고 막대 그래프로 표현한다.

FreqDist 함수는 단어의 등장 빈도를 담는 class이다.

word

['인천', '뉴시스', '루비', '기자', '인천', '테크노', '파크', '로고' ~]
word_frequency = nltk.FreqDist(word)
FreqDist({'데이터': 538, '분석': 252, '서비스': 154, '빅데이터': 115, '활용': 102, '기업': 96, '기술': 93, '개발': 89, '사업': 86, '고객': 86, ...})

여기서 key값이나 value값만 뽑을 수 있다.

word_frequency.keys() / .values()

이제, 데이터 프레임에 index 값은 key값으로 넣고, data 값은 value 값으로 넣는 작업을 하자.

df = pd.DataFrame(list(word_frequency.values()), word_frequency.keys())

열의 이름도 넣을 수 있다.

df = pd.DataFrame({'출현 빈도' : list(word_frequency.values())})
df.index = word_frequency.keys()

이제 내림차순 정렬 후, 상위 50개의 단어만 가져오는 작업을 해줍니다.

df_sort = df.sort_values([0], ascending=False)
df_sort[:50]

df의 value 값으로 정렬을 하고, 0번째 열을 기준으로 정렬한다는 뜻입니다.

이제 막대그래프로 그려줍니다.

df_sort.plot(kind='bar',legend=False, figsize=(15,5)
plt.show()

그래프 형태는 많이 있습니다.

 

이제 WordCloud를 만들어 봅시다.

WordCloud란, 많이 사용한 단어는 크게, 적게 사용한 단어는 작게 만드는 것입니다.

WordCloud를 사용하기 위해서는 WordCloud library와 각 단어의 출현 빈도수가 담긴 dict 값이 필요합니다.

from wordcloud import WordCloud
import matplotlib.pyplot as plt
from PIL import Image 

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
word_dic

{'인천': 15, '뉴시스': 13, '루비': 2, '기자': 20, '테크노': 3, '파크': 3, '로고': 1, '이미지': 12, ~ }

이제 WordCloud를 만들면 됩니다.

WordCloud 코드를 만들때, WordCloud 함수는 도화지라고 생각하면 편합니다. 

도화지 위에 내가 원하는 그림을 자유롭게 그리면 됩니다.

word_cloud = WordCloud(font_path="C:/Windows/Fonts/malgun.ttf",
			width=2000, height=1000,
                          background_color='white')
                          
word_cloud.generate_from_frequencies(word_dic)

이것이 가장 기본적인 WordCloud 코드입니다.

font_path는 어떤 폰트를 사용하는지 물어보는 것입니다.

 width=2000, height=1000는 jupyter notebook에 표현되는 크기가 아니라 컴퓨터로 저장했을때 해상도를 의미합니다.

해상도는 높으면 화질이 선명해지지만 WordCloud를 그리는데 시간이 오래걸리게 됩니다.

prefer_horizontal= 1.0 라는 코드는 글씨가 가로로만 작성되게 합니다.

 

word_cloud.generate_from_frequencies(word_dic)는 frequencies 출현 빈도 순서로 (word_dic)의 데이터를 사용해서

word_cloud를 generate 생성해달라는 코드입니다.

 

이제 실제 WordCloud를 그리는 코드입니다.

plt.figure(figsize=(15,15))
plt.imshow(word_cloud)
plt.axis("off")
plt.tight_layout(pad=0)
plt.show()

figure(figsize=(15,15))는 화면에서 보여지는 크기를 수정할 수 있는 코드입니다.

imshow(word_cloud)는 image show의 약자입니다. word_cloud를 화면에 보여주는 실질적인 코드입니다.

.axis()를 on으로 하면 가로 세로 축의 값을 보여줍니다.

tight_layout(pad=0)는 여백을 없애달라는 코드입니다. strip()함수와 비슷합니다.

바탕화면 색깔은 검은색으로, 최대 단어 갯수는 50개, 최대 폰트 사이즈는 100으로 수정해보겠습니다.

word_cloud = WordCloud(font_path="C:/Windows/Fonts/malgun.ttf",
			width=2000, height=1000,
           		 max_words = 50,
           		 max_font_size = 100
                          background_color='Black').generate_from_frequencies(word_dic)
                          
plt.figure(figsize=(15,15))
plt.imshow(word_cloud)
plt.axis("off")
plt.tight_layout(pad=0)
plt.show()

 

그림 위에 텍스트 데이터를 올려둘 수 있습니다.

우선 그림 파일부터 열어줍니다.

Image.open("python_mask.jpg")

이제 이 이미지 파일을 배열로 바꾼 뒤, WordCloud에게 넘겨 줘야 합니다.

python_coloring = np.array(Image.open("python_mask.jpg"))

word_cloud = WordCloud(font_path="C:/Windows/Fonts/malgun.ttf",
                       width=2000, height=1000, 
                       mask=python_coloring,
                       background_color='white').generate_from_frequencies(word_dic)

plt.figure(figsize=(15,15))
plt.imshow(word_cloud)
plt.axis("off")
plt.tight_layout(pad=0)
plt.show()
np.array(Image.open("python_mask.jpg")).shape

(1200, 1200, 3)

이때, (1200, 1200)은 이미지 파일의 크기이며, 3은 rgb가 겹친 정도를 말해줍니다.

이 정보가 있어야 rgb 위에 한글 폰트가 올라가게 됩니다.

특정 테두리에 특정 색깔만 지정해줄 수도 있습니다.

이때는 plt.imshow를 수정해주면 됩니다.

from wordcloud import ImageColorGenerator

python_coloring = np.array(Image.open("python_mask.jpg"))
image_colors = ImageColorGenerator(python_coloring)

word_cloud = WordCloud(font_path="C:/Windows/Fonts/malgun.ttf", 
                       width=2000, height=1000,  
                       mask=python_coloring, 
                       background_color='white').generate_from_frequencies(word_dic)
                       
plt.figure(figsize=(15,15))
plt.imshow(word_cloud.recolor(color_func=image_colors), interpolation='bilinear')
plt.axis("off")
plt.tight_layout(pad=0)
plt.show()

word_cloud.recolor은 word_cloud를 recolor 다시 칠한다는 뜻입니다.

()안에 다시 칠할 조건이 들어있습니다.

color_func=image_colors는 원본 이미지 색깔에 맞춰서 다시 칠해달라는 뜻입니다.

interpolation='bilinear'는 무시해도 되는데, 세세한 부분을 보안한다는 뜻입니다.

 

여기서 원본 이미지 색깔 말고 우리가 원하는 색깔을 넣을 수 있습니다.

이때 ()안에 colormap='Blues'와 같이 우리가 원하는 색깔을 넣어주면 됩니다.

 

다 끝난 뒤 저장은 다음 코드를 사용하면 됩니다.

word_cloud.to_file("word_cloud_completed.png")