단어사이의 관계를 그래프로 표현
특정 하나의 문장에 같이 나오는 단어쌍 빈도를 기반으로 시각화
파이썬의 networkx 모듈 활용
https://networkx.org/documentation/stable/tutorial.html
Tutorial — NetworkX 3.4.2 documentation
Tutorial This guide can help you start working with NetworkX. Creating a graph Create an empty graph with no nodes and no edges. import networkx as nx G = nx.Graph() By definition, a Graph is a collection of nodes (vertices) along with identified pairs of
networkx.org
노드--엣지--노드
엣지에 가중치를 넣어줄 수 있음
networkx의 알고리즘
연결 중심성 : 중심성을 나타냄. 단어쌍 빈도에 직결됨.
페이지 랭크 : 고유벡터 중심성에 무작위성, 정규화가 추가됨. 추가적 핵심 키워드 찾을때 유용.
매개 중심성 : 노드와 노드 사이 통과하는 엣지 수
근접 중심성 : 노드와 노드사이 최단 경로 길이 기반으로 중심성 나타냄.
고유 벡터 중심성 : 노드간 중심성을 반영해서 상대적 중심성 계산
중심이 될 단어를 선별
center = '선물'
isin_df = store_df[store_df['text_tag'].str.contains(center)]
isin_df
'선물' 키워드를 포함하고 있는 인덱스 선별
단어쌍 빈도 구하기
dictionary를 활용
count = {}
for line in isin_df['text_tag']:
words = list(set(line.split()))
for i, a in enumerate(words):
for b in words[i + 1:]: # 앞뒤 단어를 사전으로 묶어 카운트 (앞뒤가 달라도 동일하게)
if a > b:
count[b, a] = count.get((b, a), 0) + 1
else:
count[a, b] = count.get((a, b), 0) + 1
net_list = [(w[0], w[1], count[w]) for w in count]
net_df = pd.DataFrame(net_list, columns=['w1', 'w2', 'f']) # 데이터프레임으로 변환
net_df = net_df.sort_values(by=['f'], ascending=False) # 빈도수로 정렬
net_df = net_df[net_df['f'] > 10] # 너무 적은 빈도는 제외
net_df
단어쌍 빈도 활용하여 네트워크 그래프 생성 및 연결 중심성 연산
import networkx as nx
G_cen = nx.Graph()
## 1차 그래프 그리기
# 두단어를 두개의 노드로 그리기
# 두단어를 엣지로 연결하고 엣지에 가중치 할당
for net in net_df.iloc: #관측치 하나씩 나오게
G_cen.add_edge(net['w1'], net['w2'], weight=int(net['f']))
#빈도쌍에 대한 값을 int로 형변환해서 넣어줌
# # 1차 그래프를 활용해 중심성 알고리즘으로 노드의 크기 연산
# centrality = nx.degree_centrality(G_cen) # 연결중심성
centrality = nx.pagerank(G_cen) # 페이지링크
centrality
#페이지링크 결과
{'구매': 0.03917531010505659,
'선물': 0.22509241953417244,
'잘': 0.024849369490794346,
'친구': 0.018723770625026486,
...}
#페이지링크 부분을 주석처리하고 연결중심성으로 결과구할수도있음
연결 중심성 결과 값으로 그래프 재생성
## 2차 그래프 그리기
G = nx.Graph()
nsize = 20000 # 노드 크기 (배수)
w_size = 30 # 표현될 상위 키위드 개수
# 중심성 알고리즘을 통해 연산한 단어의 중심값을 노드의 크기로 설정
node_size = []
for node in list(centrality)[:w_size]: #중심성 알고리즘 값을 중심성으로 넣어줌
#상위 30개의 중심성 단어를가져옴
G.add_node(node) #노드를 쭉 추가시킴
node_size.append(centrality[node]*nsize) #중심성 값을 사이즈 추가 (필수는 아님)
#노드의 크기 -> 연결중심성 값이라고 보면 됨
# 엣지 가중치는 빈도수로 동일하게 설정
for net in net_df.iloc:
if net['w1'] in G.nodes and net['w2'] in G.nodes:
#내가 넣어놓은 단어인 경우에만 엣지를 추가하는 방식
G.add_weighted_edges_from([(net['w1'], net['w2'], int(net['f']))])
node_size
matplotlib으로 노드와 엣지를 시각적으로 표현
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc
plt.rc('font', family='Malgun Gothic')
plt.figure(figsize=(10,10))
gcolor = '#616161'
ax = plt.subplot()
k = 0.3 # 상수 k값 클수록 중앙 밀집도가 커짐
pos = nx.spring_layout(G, k=k)
nx.draw_networkx(G, pos,
ax = ax, # Axes
node_size=node_size, # 노드 크기
with_labels=True, # 라벨표기 옵션 True (글자 표현)
edge_color=gcolor, # 엣지(연결선) 컬러
edgecolors='#0d47a1', # 노드의 테두리
node_color='lightgray', # 노드 컬러
font_weight='regular', # 폰트설정
font_family= 'Malgun Gothic') #글꼴
for i in 'top bottom right left'.split():
ax.spines[i].set_visible(False)
ax.tick_params(left=False, right=False, labelleft=False,
labelbottom=False, bottom=False)
ax.set_title('연결 중심성 [선물]', fontsize=20)
plt.show()
페이지랭크와 연결중심성 두가지 해보고 비교해보면 약간의 차이가 있음
중심성을 볼때는 연결중심성, 많은 키워드를 볼때는 페이지랭크 활용
그래프를 보고 불용어로 제거할 곳은 제거하기를 반복
'데이터 분석 > 키워드 분석' 카테고리의 다른 글
[실습] 텍스트 시각화 (2) | 2025.01.23 |
---|---|
[이론] 텍스트 시각화 - LDA 토픽 모델링 (2) | 2025.01.22 |
[이론] 텍스트 시각화 - 워드 클라우드 (1) | 2025.01.22 |
[이론] 텍스트 시각화 - 빈도 & TF-IDF 그래프 (1) | 2025.01.22 |
[이론] 벡터화 (2) | 2025.01.21 |