์ด๋ฒ ํฌ์คํ ์์๋ ๊ต๋ณด๋ฌธ๊ณ ๋ฐ์ดํฐ๋ฅผ ํตํด KoNLPy์ WordCloud๋ฅผ ํ์ฉํด ํค์๋ ์ถ์ถ๋ถํฐ ์๋ํด๋ผ์ฐ๋ ์๊ฐํ๊น์ง ํ ๋ฒ์ ํด๋ณด๊ฒ ์ต๋๋ค!
๐ก NanumGothic ํฐํธ๋ง ์ฐ๋ฉด ๊ธ์๊ฐ ๊นจ์ง๋ ๊ฒฝ์ฐ๊ฐ ์์ ์ ์๋๋ฐ, ๋ค๋ฅธ ํฐํธ๋ฅผ Fallback(๋์ฒด ํฐํธ)์ผ๋ก ์ค์ ํด์ ์๋ฌ๋ฅผ ์ต์ํํด๋ด ์๋ค!
๋จผ์ ๊ต๋ณด๋ฌธ๊ณ ์ฌ์ดํธ์์ ์ํ๋ ์นดํ ๊ณ ๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ์์ ๋ก ์ถ์ถํ๋ค๊ณ ๊ฐ์ ํด๋ณผ๊ฒ์. (์ค์ ๋ก๋ ์น ํฌ๋กค๋ง, ๋ค์ด๋ก๋, ๋๋ ์ง์ ์ ๋ฆฌ ๋ฑ ๋ค์ํ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ์ค ์ ์์ต๋๋ค.)
(์ ์ด๋ฏธ์ง๋ ์์์ ๋๋ค. ์ค์ ๊ต๋ณด๋ฌธ๊ณ ์ฌ์ดํธ์์ ๋ฐ์ดํฐ ํ์ธ!)
ํด๋น ์์
ํ์ผ์ ํ๋ก์ ํธ ํด๋์ ๋ฃ์ด ๊ต๋ณด๋ฌธ๊ณ _์นดํ
๊ณ ๋ฆฌ_์ํ๋ฆฌ์คํธ.xlsx
๋ผ๋ ์ด๋ฆ์ผ๋ก ์ ์ฅํด๋ก๋๋ค.
์๋๋ NanumGothic ํฐํธ๋ฅผ ์ฐ์ ์ฌ์ฉํ๋, ํฐํธ์ ๋๋ฝ๋ ๊ธ๋ฆฌํ๊ฐ ์์ผ๋ฉด ๋ค๋ฅธ ํฐํธ๋ก ๋์ฒดํ๋๋ก ์ค์ ํ ์ ์ฒด ์ฝ๋์์. ์ด๋ฐ ๋ฐฉ์์ผ๋ก "missing from current font" ๋ฌธ์ ๋ฅผ ์ํํ ์ ์์ต๋๋ค.
import os
import pandas as pd
from konlpy.tag import Okt
from collections import Counter
import matplotlib.pyplot as plt
import seaborn as sns
from wordcloud import WordCloud
import matplotlib.font_manager as fm
# -----------------------------
# 1. ํฐํธ ์ค์
# -----------------------------
# (1) NanumGothic ํฐํธ (์ฐ์ ์ฌ์ฉ)
# (2) ๋ง์ฝ ํน์ ๊ธ๋ฆฌํ ๋๋ฝ ์ AppleGothic, Malgun Gothic ๋ฑ fallback
# ๊ฐ์ ๋ก NanumGothic ํฐํธ ๋ฑ๋ก
nanum_font_path = '/Users/kimdonghyuk/Library/Fonts/NanumGothic-Regular.ttf'
fm.fontManager.addfont(nanum_font_path)
# ์ฌ๋ฌ ํฐํธ๋ฅผ ์์๋๋ก ์ง์ ํ์ฌ ๋๋ฝ๋ ๊ธ๋ฆฌํ ๋ฌธ์ ์ํ
plt.rcParams['font.family'] = [
'NanumGothic', # ์ฐ์ ์๋
'AppleGothic', # macOS ๊ธฐ๋ณธ ํ๊ธ ํฐํธ (fallback)
'Malgun Gothic', # Windows ๊ธฐ๋ณธ ํ๊ธ ํฐํธ (fallback)
'sans-serif' # ๊ธฐ๋ณธ sans-serif ํฐํธ
]
plt.rcParams['axes.unicode_minus'] = False # ์์ ๊ธฐํธ ๊นจ์ง ๋ฐฉ์ง
print("๐ข ํฐํธ ์ค์ ์๋ฃ: NanumGothic -> AppleGothic -> Malgun Gothic ์์ผ๋ก ํ์ธํฉ๋๋ค!")
# -----------------------------
# 2. ์์
๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ
# -----------------------------
file_path = '๊ต๋ณด๋ฌธ๊ณ _์นดํ
๊ณ ๋ฆฌ_์ํ๋ฆฌ์คํธ.xlsx' # ์์
ํ์ผ ๊ฒฝ๋ก
df = pd.read_excel(file_path)
print(f"โ
๋ฐ์ดํฐ ๋ก๋ ์ฑ๊ณต: {file_path}")
# -----------------------------
# 3. ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ
# -----------------------------
required_columns = ['์ํ๋ช
', '์ ๊ฐ', 'ํ๋งค๊ฐ', 'ํ ์ธ์จ', '์ ๋ฆฝ์จ', '์ ๋ฆฝ์์ ํฌ์ธํธ', '์ถํ์ฌ']
# ํ์ํ ์ปฌ๋ผ์ด ๋ชจ๋ ์๋์ง ์ฒดํฌ
missing_cols = [col for col in required_columns if col not in df.columns]
if missing_cols:
raise KeyError(f"๋ค์ ์ปฌ๋ผ๋ค์ด ๋๋ฝ๋์์ต๋๋ค: {missing_cols}")
df = df[required_columns]
numeric_columns = ['์ ๊ฐ', 'ํ๋งค๊ฐ', 'ํ ์ธ์จ', '์ ๋ฆฝ์จ', '์ ๋ฆฝ์์ ํฌ์ธํธ']
for col in numeric_columns:
df[col] = df[col].astype(str).str.replace(',', '').str.replace('%', '').astype(float)
print("โ
๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ ์๋ฃ")
# -----------------------------
# 4. ํค์๋ ์ถ์ถ (KoNLPy)
# -----------------------------
okt = Okt()
stopwords = ['๊ธฐ์ ', '์ด๋ก ', '๊ธฐ๋ณธ์', '๋ฌธ์ ์ง', '์ค๋ฌด', '๊ธฐ์ถ', 'ํ๊ธฐ', '์ค๊ธฐ'] # ๋ถ์ ์ ์ธํ ๋จ์ด๋ค
all_nouns = []
for title in df['์ํ๋ช
']:
nouns = okt.nouns(title) # ๋ช
์ฌ๋ง ์ถ์ถ
filtered = [n for n in nouns if n not in stopwords and len(n) > 1]
all_nouns.extend(filtered)
print("โ
ํค์๋ ์ถ์ถ ์๋ฃ")
# -----------------------------
# 5. ๋น๋์ ๋ถ์
# -----------------------------
word_counts = Counter(all_nouns)
top_keywords = word_counts.most_common(20)
keywords_df = pd.DataFrame(top_keywords, columns=['ํค์๋', '๋น๋์'])
print("โ
๋น๋์ ๋ถ์ ์๋ฃ")
print(keywords_df.head(10))
# -----------------------------
# 6. ๋ฐ์ดํฐ ์๊ฐํ
# -----------------------------
sns.set(style="whitegrid")
# (1) ๋ง๋ ๊ทธ๋ํ ์๊ฐํ
plt.figure(figsize=(12, 8))
sns.barplot(x='๋น๋์', y='ํค์๋', data=keywords_df, palette='viridis')
plt.title('๐ ์์ 20๊ฐ ํค์๋ ๋น๋์')
plt.xlabel('๋น๋์')
plt.ylabel('ํค์๋')
plt.show()
# (2) ์๋ํด๋ผ์ฐ๋ ์์ฑ
try:
wordcloud = WordCloud(
font_path=nanum_font_path, # NanumGothic ํฐํธ ์ง์
background_color='white',
width=800,
height=600
).generate_from_frequencies(dict(word_counts))
plt.figure(figsize=(12, 8))
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis('off')
plt.title('๐ ํค์๋ ์๋ํด๋ผ์ฐ๋')
plt.show()
except ValueError as e:
print(f"โ ๏ธ ์๋ํด๋ผ์ฐ๋ ์์ฑ ์ค ๋ฌธ์ ๋ฐ์: {e}")
ํฐํธ ์ค์
matplotlib
์ rcParams['font.family']
์ ์ฌ๋ฌ ํฐํธ๋ฅผ ๋ฆฌ์คํธ๋ก ๋ฃ์ด๋๋ฉด, ์์ ํฐํธ์์ ๊ธ๋ฆฌํ๊ฐ ์์ผ๋ฉด ๋ค์ชฝ ํฐํธ๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด missing from current font ์๋ฌ๋ฅผ ํฌ๊ฒ ์ํํ ์ ์์ต๋๋ค.์์ ํ์ผ ์ฝ๊ธฐ
pandas
๋ก ๊ต๋ณด๋ฌธ๊ณ ์์ ์ถ์ถํ ์์
ํ์ผ์ ์ฝ์ด์ต๋๋ค.๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ
,
)์ ํผ์ผํธ(%
)๋ฅผ ์ ๊ฑฐํด ์ซ์ํ์ผ๋ก ๋ณํํฉ๋๋ค.KoNLPy๋ก ํค์๋ ์ถ์ถ
Okt
ํํ์ ๋ถ์๊ธฐ๋ฅผ ์ฌ์ฉํด ๋ช
์ฌ๋ฅผ ์ถ์ถํ ๋ค, ๋ถ์ฉ์ด ๋ฆฌ์คํธ(stopwords
)์์ ์ ๊ฑฐํฉ๋๋ค.๋น๋์ ๋ถ์ & ์๊ฐํ
collections.Counter
๋ก ํค์๋ ๋น๋์๋ฅผ ๊ณ์ฐํ๊ณ , Seaborn
๋ง๋ ๊ทธ๋ํ๋ก ์์ 20๊ฐ ํค์๋ ๋น๋์๋ฅผ ํ์ธํฉ๋๋ค.WordCloud
๋ก ์๋ํด๋ผ์ฐ๋๋ฅผ ์์ฑํ์ฌ ํค์๋๋ฅผ ์ง๊ด์ ์ผ๋ก ํ์
ํ ์ ์์ต๋๋ค.์ด๋ฒ ํฌ์คํ ์์๋ ๊ต๋ณด๋ฌธ๊ณ ๋ฐ์ดํฐ๋ฅผ ๋ถ์ํ๋ฉฐ, ํ๊ธ ํฐํธ ์ด์๋ฅผ ์ต์ํํ๊ธฐ ์ํด Fallback ํฐํธ๋ฅผ ์ง์ ํ๋ ๋ฐฉ๋ฒ์ ์ดํด๋ดค์ด์! ๐
โจ
์ผ๋ณธ ๋งฅ์์ ํ๊ธ ํฐํธ ์ค์ ์ด ์ด๋ ค์ ํ๊ธ์ ํฌ๊ธฐํ์ง๋ง, ๋ถ์๊ณผ ์๊ฐํ๋ฅผ ๋๊น์ง ์์ฑํ์ต๋๋ค!
ํฐํธ ๋ฌธ์ ๋ก ๊ณ ์ํ์๋ ๋ถ๋ค์ ์ ์ฒ๋ผ ์์ด ๊ธฐ๋ฐ์ผ๋ก ๋์ฒดํ๊ฑฐ๋, ํ๊ธ ํฐํธ๋ฅผ ์ค์นํด ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ฐพ์ผ์๋ฉด ์ข๊ฒ ์ต๋๋ค..
๊ถ๊ธํ ์ ์ด๋ ์ถ๊ฐ ์๊ฒฌ์ด ์๋ค๋ฉด ๋๊ธ๋ก ๋จ๊ฒจ์ฃผ์ธ์!
์ฌ๋ฌ๋ถ์ ๋ถ์์๋ ๋์์ด ๋์๊ธธ ๋ฐ๋๋๋ค. ๐
๋ฐ์ดํฐ ์ถ์ฒ: ๊ต๋ณด๋ฌธ๊ณ
์ฐธ๊ณ ๋ผ์ด๋ธ๋ฌ๋ฆฌ:
๊ฐ์ฌํฉ๋๋ค! ๐ ์ฆ๊ฑฐ์ด ๋ฐ์ดํฐ ๋ถ์ ๋์ธ์!