데이터 리터러시를 위한 발자취

[NLP] KRWordRank 기반 워드클라우드 시각화 본문

데이터 분석/Python

[NLP] KRWordRank 기반 워드클라우드 시각화

wosole 2024. 1. 17. 17:22

출처 : DALL-E 활용

 

안녕하세요, 지난번 BigQuery에 이어 NLP 기반 워드클라우드 시각화 구현한 부분을 다루고자 합니다. 

 

본문에 사용된 데이터는 '프리온보딩 원티드 데이터 챌린지 1월' 과정에서 제공된 데이터를 활용한 점 참고 부탁드려요.

또한, 하단 GitHub의 KRWordRank를 활용하여 키워드 추출 및 워드클라우드 시각화를 진행하였습니다.

 

GitHub - lovit/KR-WordRank: 비지도학습 방법으로 한국어 텍스트에서 단어/키워드를 자동으로 추출하는

비지도학습 방법으로 한국어 텍스트에서 단어/키워드를 자동으로 추출하는 라이브러리입니다. Contribute to lovit/KR-WordRank development by creating an account on GitHub.

github.com

내용은 아래와 같이 진행될 예정입니다.

# KRwordRank 기반 워드클라우드 시각화
1. BigQuery 데이터 조회
2. Python 기반 키워드 추출 
3. 워드클라우드 시각화

1. BigQuery 데이터 조회

- 키워드 추출을 위해 jd 컬럼 내, 주요업무, 자격요건, 우대사항, 혜택 및 복지 단어를 구분하여 4개의 컬럼으로 할당 진행

 

➡️출력조건(예시) : jd 컬럼을 ‘주요업무’, ‘자격요건’, ‘우대사항’, ‘혜택 및 복지’ 단어로 구분하여 컬럼을 4개로 나누기

- 컬럼명은 responsibilities, requirements, preference, benefits로 명명

 

1) split 및 safe_offset 기반 데이터 컬럼 나누기

*️⃣ 코드 일부 해석 : SPLIT(split(jd,'주요업무')[SAFE_OFFSET(1)],'자격요건')[SAFE_OFFSET(0)] AS responsibilities

- jd 컬럼의 '주요업무'란 단어 기준으로 분할한 후, 1번째 결과를 가져옴 (첫 번째 인덱스,SAFE_OFFSET(1))

- 이후 '자격요건' 전까지의 결과를 가져옴 (0번째 인덱스, SAFE_OFFSET(0))

# 함수별 기본 사용법
SPLIT(컬럼명, '나누고싶은단어')
[SAFE_ORFFSET(n)] : 나눈 것중 n번째 결과 가져오기, n번째 결과가 없을 경우 null 출력

SELECT
  position_id,
  SPLIT(split(jd,'주요업무')[SAFE_OFFSET(1)],'자격요건')[SAFE_OFFSET(0)] AS responsibilities,
  SPLIT(split(SPLIT(jd,'주요업무')[SAFE_OFFSET(1)],'자격요건')[SAFE_OFFSET(1)],'우대사항')[SAFE_OFFSET(0)] AS requirements,
  SPLIT(split(SPLIT(split(jd,'주요업무')[SAFE_OFFSET(1)],'자격요건')[SAFE_OFFSET(1)],'우대사항')[SAFE_OFFSET(1)],'혜택 및 복지')[SAFE_OFFSET(0)] AS preference,
  SPLIT(split(SPLIT(split(jd,'주요업무')[SAFE_OFFSET(1)],'자격요건')[SAFE_OFFSET(1)],'우대사항')[SAFE_OFFSET(1)],'혜택 및 복지')[SAFE_OFFSET(1)] AS benefits,
  annual_from,annual_to
FROM
  데이터세트명.테이블명;

 

➡️출력 결과

출력 조건에 맞는 컬럼으로 분할 완료


2. Python 기반 키워드 추출 

- 상단 이미지 체크 부분과 같이 '데이터 탐색' - 'Python 노트북으로 탐색' 클릭

- Google Coolab 활성화되며 Setup, Reference SQL syntax from the original job,  Result set loaded from BigQuery job as a DataFrame는 내용 변경없이 그대로 실행해주기

 

1) 원본 DataFrame 보존을 위해 데이터프레임 copy 수행 

 

2) KRwordRank 패키지 설치 및 데이터 전처리

# 패키지 설치
!pip install krwordrank

 

➡️ 데이터 결측치 제거 및 데이터 전처리

# 라이브러리 import
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from krwordrank.word import KRWordRank
from krwordrank.hangle import normalize

# 컬럼별 결측치 제거 
df['responsibilities'] = df['responsibilities'].replace(np.nan, '없음')
df['requirements'] = df['requirements'].replace(np.nan, '없음')
df['preference'] = df['preference'].replace(np.nan, '없음')
df['benefits'] = df['benefits'].replace(np.nan, '없음')

# 'requirements' 값 추출 및 리스트 변환
data  = df["requirements"].values.tolist()

 

- 데이터 추출 여부는 리스트로 저장된 'data'를 새로운 데이터프레임으로 생성하여 확인함

 

3) 키워드 추출 및 불용어 처리 - GitHub 참고

from krwordrank.word import KRWordRank

wordrank_extractor = KRWordRank(
    min_count = 3, # 단어 최소 출현 빈도수
    max_length = 15, # 단어의 character 길이의 최대 값
    verbose = True
)

beta = 0.85
max_iter = 10
keywords, rank, graph = wordrank_extractor.extract(data, beta, max_iter)

for word, r in sorted(keywords.items(), key=lambda x:x[1], reverse=True)[:30]: # 상위 30개까지 출력
    print('%8s:\t%.4f' % (word, r))

 

➡️출력 결과(불용어 처리 전)

- 키워드 30개까지 출력된 결과, 불용어 처리 시 제외되어야 할 단어들 확인(and, in,to 등)

 

➡️ 불용어 처리 

# 불용어 지정
stopwords = {'대한', '분이면', '있습니다.', '분석', '데이터', '위한', 'and', '통해', '통한', '있는', 'the', 'to', 'in', 'for', 'of', 'and','등)','있으','등을','or','관련','또는',
             '경험','이상','개발','활용','능력','가능','사용','등의','(e.g.',',','기반','경력','프로','다양한','업무'}

# keywords를 점수에 따라 내림차순 정렬, 상위 300개 선택
passwords = {word: score for word, score in sorted(
    keywords.items(), key=lambda x: -x[1])[:300] if word not in stopwords}

# passwords에서 생성된 키워드 및 점수를 내림차순 정렬, 상위 30개까지 출력
for word, r in sorted(passwords.items(), key=lambda x: x[1], reverse=True)[:30]:
    print('%8s:\t%.4f' % (word, r))

 

➡️ 불용어 제거 후, 출력 결과


3. 워드클라우드 시각화

1) 한글 폰트 설치

- 코랩의 경우, 한글 폰트를 지원하지 않기 때문에 아래와 같이 설치 필요

# 한글폰트 세팅
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm # 폰트매니저

# 그래프 이미지의 해상도 설정
%config InlineBackend.figure_format = 'retina'

# Nanum 폰트 설치
!sudo apt-get install -y fonts-nanum
!sudo fc-cache -fv
!rm ~/.cache/matplotlib -rf

# 폰트 경로 설정
path = '/usr/share/fonts/truetype/nanum/NanumBarunGothic.ttf' # NanumBarunGothic 폰트 경로 지정

# 폰트 엔트리 생성
fe = fm.FontEntry(
    fname=path, # ttf 파일이 저장되어 있는 경로
    name='NanumGothic') # 이 폰트의 원하는 이름 설정

# Matplotlib에 폰트 추가
fm.fontManager.ttflist.insert(0, fe)

# Matplotlib 기본 설정 업데이트
plt.rcParams.update({'font.size': 10, 'font.family': 'NanumGothic'})

 

2) 워드클라우드 설치 및 시각화

# 워드클라우드 패키지 설치
!pip install wordcloud

 

➡️워드클라우드 시각화

from wordcloud import WordCloud
from wordcloud import ImageColorGenerator

# 워드클라우드 설정
wordcloud = WordCloud(
    font_path = path,
    background_color='white',
    width=800,  # 예: 800 픽셀
    height=800,   # 예: 800 픽셀
    max_font_size = 250
).generate_from_frequencies(passwords)

# 워드클라우드 시각화
plt.figure(figsize=(5, 5), dpi=120)
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis('off')
plt.show()

 

➡️ 출력 결과

- 한글 깨짐 현상 없이 정상 출력되는 것을 확인

- JD 분석 결과, SQL, Python, R, 통계 등 기술적 역량 외에도 통계, 원활한 커뮤니케이션, 모델 지식 등을 요구하는 점 확인


워드클라우드 시각화 과정에서 width, height 값을 미설정하니 이미지가 흐릿하게 나오는 것을 확인했습니다.

 

이 부분은 width, height를 설정해줌으로써 상단과 같은 결과를 얻을 수 있었네요.

 

조금 더 의미있는 결과 도출을 위해선, anuual_from 및 anuual_to의 기간을 설정하여 요구하는 연차별 어떤 역량을 더 중요시하는지, 직무에 따라서는 중요한 역량이 무엇인지를 살펴볼 수 있을 것이라 생각됩니다 😀

 

다만 NLP 패키지는 KRwordRank 외에도 KoNLPy, Mecab-ko 등 다양하게 존재하고 있기 때문에 활용 목적에 따라서 여러 패키지를 활용할 수 있을 것 같습니다 :) 

 

예전에 KoNLPy 기반 Okt를 써본 적이 있는데, 데이터를 돌리는 것보다 결측치나 전처리 과정이 더 힘들었던 기억이 있네요 😅 

 

NLP 맛보기 수준으로 다룬 내용이지만 관심 있으신 분들은 최상단 github 링크를 통해 연습해보시는 것도 좋을 것 같습니다!

 

긴 글 읽어주셔서 감사합니다-!

 

 

 

Comments