WordCloud는 텍스트 기반의 문서에서 키워드, 단어, 자주 사용하는 단어를 추출하여 핵심 내용을 직관적으로 파악할 수 있도록 그래픽으로 가시화하는 방법입니다. Python으로 WordCloud를 생성하기 위해서는 아래와 같은 3가지 단계가 필요합니다.
- KoNLPy와 nltk lib를 사용해서 문서에서 각각의 형태소(≒ 주로 명사인 단어)로 추출
- Collection Counter() 모듈을 사용해서 명사가 언급된 횟수를 계산
- WordCloud Lib를 사용하여 형태소(단어) 빈도에 따른 WordCloud 이미지 생성 및 저장
한국어 형태소 분석 KoNLPy (Korean NLP in Python)
한국어 자연어 처리 Python 오픈소스인 KoNLPy를 사용합니다. KoNLPy의 소스 코드와 홈 페이지는 https://github.com/konlpy/konlpy와 https://konlpy.org/ko/latest/ 입니다. KoNLP에서는 Kkma, Twitter, Komoran의 Tokenizer를 지원하며 각각에 대한 성능은 홈페이지에서 확인 가능하며, 이중에서 Twitter 방법을 사용할 예정입니다.
KoNLPy 설치
KoNLPy는 Java가 먼저 설치되어 있어야 합니다.
$ sudo apt-get install openjdk-7-jdk
$ sudo apt-get install python-dev
$ sudo pip3 install konlpy
KoNLP는 Lib의 API는 Python으로 구현되어 있지만, 실제 자연어 처리는 Java code에서 처리합니다. 예를 들어 KoNLPy 설치 후 __okt.py 파일에서 __init__() 함수를 확인해보면 kr.lucypark.okt java pakcage를 로딩하는 것을 알 수 있습니다.
KoNLPy 사용해서 문장에서 명사 단어를 추출
KoNLPy lib는 morphs(), normalize(), nouns(), pos() 등의 형태소 관련해서 다양한 함수를 지원합니다. noun() 함수를 포함하여 morph(), pos() 함수에 대한 실행 결과는 아래 그림을 참고해주세요.
이 중에서는 WordCloud에서는 noun() 함수를 사용해서 명사를 추출하여 list로 만들고, 이를 빈도에 따라서 WordCloud 그래프로 그릴 예정입니다. 문장에서 Okt (Twitter) 방식으로 형태소를 분석하고 이 중에서 명사를 추출하는 방법은 아래 tokenizer_konlpy()와 같이 구현합니다. 분리한 명사에서 단어의 문자 개수가 1개 이상인 것으로 추출합니다.
def tokenizer_konlpy(text):
okt = Okt()
return [word for word in okt.nouns(text) if len(word) >1]
Collection Counter() 모듈를 사용해서 단어가 언급된 횟수를 계산
KoNLPy에 의해서 명사인 단어를 추출한 상태에서 다음 단계는 빈도를 계산하는 단계입니다. 빈도를 계산하는 모듈은 Built-in함수의 collection 모듈의 count.most_common() 함수를 사용합니다.
# count word
count = Counter(noun)
# get most frequent words
noun_list = count.most_common(3000)
Counter 모듈에 대한 설명은 https://docs.python.org/ko/3/library/collections.html#collections.Counter에 설명이 있습니다 (아래 그림 참조).
WordCloud Lib를 사용하여 형태소 (단어) 빈도에 따른 WordCloud 이미지 생성 저장
WordCloud 모듈이 설치되어 있지 않은 경우 pip3를 통해서 먼저 wordcloud를 설치해야 합니다.
# wordcloud 설치
$ sudo pip3 install wordcloud
Python code에서는 아래와 같이 WordCloud 객체를 만들고, wc.generate_from_frequencies()에 단어 list를 전달하고 이미지 파일로 저장합니다. WordCloud() 객체 생성 시 한글인 경우에는 한글 폰트를 지정하지 않으면 한글이 모두 깨져 나오기 때문에 한글 폰트의 경로를 font_path를 통해서 지정해야 합니다.
# Generate a word cloud image
wc = WordCloud(font_path = './gulim.ttf',
background_color = 'white',
width=512, height=512,
max_font_size=500,
max_words=1000)
wc.generate_from_frequencies(dict(noun_list))
# Save to png
wc.to_file(output_file)
WordCloud 생성 결과와 전체 Sample code
블로그 중 하나를 Text파일로 만들어서 WordCloud 생성하고 PNG로 저장한 결과입니다. KoNLPy는 한글만 처리하고 있기 때문에 한글만 표시되고 있고, 영어도 포함되어 있는 경우에는 nltk 모듈을 사용해서 명사만 추출할 수 있습니다.
Sample Code 위치 (GitHub)
GitHub에 실제 동작하는 sample code를 정리해서 아래 링크에 올렸고, wdcloud.py 파일을 참고하면 쉽게 사용 가능합니다.
▣ GitHub 링크: https://github.com/kibua20/devDocs/tree/master/word_cloud
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from collections import Counter
from wordcloud import WordCloud
from konlpy.tag import Okt
import nltk
def wordcloud_from_text(input_file, output_file='wordcloud.png'):
# get text from file
try:
with open(input_file, "rb") as f:
text=f.read().decode('utf8')
except Exception as e:
print ('wordcloud_from_text() - %s' %(e))
return
# 예외 처리
if text == None:
print ('wordcloud_from_text() text is None')
return
# get noun list
noun_list = get_noun_list(text)
# 예외 처리 2
if len(noun_list) < 10:
print ('wordcloud_from_text() - Too small noun list')
return
# Generate a word cloud image
wc = WordCloud(font_path = './gulim.ttf',
background_color = 'white',
width=512, height=512,
max_font_size=500,
max_words=1000)
wc.generate_from_frequencies(dict(noun_list))
wc.to_file(output_file)
print ('Create WordCloud:', output_file)
#-------------------------------------------------------------------------------------------------------------------
def get_noun_list(text, method=0):
# Sentence to token
if method == 0:
# 한국어
noun = tokenizer_konlpy(text)
else:
# 영어
noun = tokenizer_nltk(text)
# count word
count = Counter(noun)
# get most frequent words
noun_list = count.most_common(3000)
return noun_list
#-------------------------------------------------------------------------------------------------------------------
def tokenizer_nltk(text):
# NNP: 단수 고유명사, VB: 동사, VBP: 동사 현재형, TO: to 전치사, NN: 명사(단수형 혹은 집합형), DT: 관형사
is_noun = lambda pos : (pos[:2] == 'NN' or pos[:2] == 'NNP')
tokenized = nltk.word_tokenize(text)
return [word for (word, pos) in nltk.pos_tag(tokenized) if is_noun(pos)]
#-------------------------------------------------------------------------------------------------------------------
def tokenizer_konlpy(text):
okt = Okt()
return [word for word in okt.nouns(text) if len(word) >1]
#-------------------------------------------------------------------------------------------------------------------
if __name__ == '__main__':
wordcloud_from_text (input_file='test.txt')
※ 참고 내용
https://liveyourit.tistory.com/57
https://github.com/chiheon/Korean-NLP
관련 글:
[SW 개발/Python] - Python: JSON 개념과 json 모듈 사용법
[SW 개발/Data 분석 (RDB, NoSQL, Dataframe)] - Apple App Store 사용자 댓글(리뷰) 데이터 수집하기 (Sample code 포함)
[SW 개발/Data 분석 (RDB, NoSQL, Dataframe)] - Pandas Dataframe 여러 열과 행에 apply() 함수 적용 (Sample code 포함)
[SW 개발/Data 분석 (RDB, NoSQL, Dataframe)] - Panda Dataframe 날짜 기준으로 데이터 조회 및 처리하기
[SW 개발/Data 분석 (RDB, NoSQL, Dataframe)] - MariaDB의 Python Connector 설치와 사용 방법
[SW 개발/Data 분석 (RDB, NoSQL, Dataframe)] - Jupyter Notebook의 업그레이드: Jupyter Lab 설치 및 extension 사용법
[개발환경/우분투] - 대용량 파일을 작은 크기로 분할하는 방법: split
[SW 개발/Android] - Python으로 개발된 Android Apk Decompile Tool: androguard
[SW 개발/Android] - Python BeautifulSoup으로 만든 Apk download 자동화 (Sample code)
댓글