Skip to content
전에 UCINET으로 네트워크 시각화 하는 방법에 대해서 적었는데, 이번에는 아예 Python으로 동시출현단어 쌍을 만들고 -> Gephi용 확장자인 graphml로 output을 산출하는 과정에 대해서 적어보고자 한다. 동시출현 단어쌍 만들기 먼저 pandas를 불러온 후에, readlines 명령어로 미리 형태소분석이 된 데이터를 불러온다. import pandas as pd f = open("파일 위치/파일명.txt", encoding='UTF8') lines = f.readlines() #라인으로 불러오기 len(lines) #라인 갯수 알아보기 lines #데이터 잘 불러와졌는지 확인 word_list를 만들어서 lines의 데이터를 넣어준다. (append) words_list=[] for text in lines: #list에 있는 lines데이터를 하나씩 불러올 때 text로 불러오는데 탭 구분으로 strip(앞뒤 공백 없애기) 해라 words_list.append(text.split('\t')[2].strip()) words_list[0] #확인하기 우선 동시출현 단어쌍을 만드는 방법에 대해서 이해해보자. temp2에 단어 4개를 집어넣은 다음에, 아래와 같이 for문을 돌려보자. temp2 = ["빠빠","엄마","누나","나"] count = {} #이 괄호는 dictionary for i, a in enumerate(temp2): #i(0,1,2,3)에는 인덱스가 나오고 a에는 temp2의 빠빠","엄마","누나","나"가 나옴 for b in temp2[i+1:]: #b에는 i에 하나씩 더해서 비교함 #if a == b: continue #같은 단어의 경우는 세지 않음 #[가,나]와 [나,가]를 같은 것으로 취급 (정렬하고 싶다) 카운트에서 if a>b: #가나다 순으로 안 되어있으면 b, a로 바꿔서 keyvalue값을 넣어줘라 count[b, a] = count.get((b, a),0) + 1 #key값이 없으면 디폴트로 0 넣기 else :#가나다 순으로 되어 있으면 그대로 가면 됨 count[a, b] = count.get((a, b),0) + 1 count 딕셔너리를 조회해보면 count 아래와 같이 4C2 (조합ㅎㅎ)인 6개 동시출현쌍에서 동시출현 횟수를 알 수 있다! count = {} #동시출현 빈도가 저장될 dict for line in words_list: #하나의 문서에서 동일한 단어가 두번 나와도 두번의 동시출현으로 고려X words = list(set(line.split())) #한줄씩 읽어와서 단어별로 분리(unique한 값으로 받아오기) #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 set(["아빠","아빠","엄마"]) count.get(("a", "b"),0) #a, b라는 key가 없을 때는 디폴트를 0으로 해라 count #dictionary형 자료형을 판다스 데이터프레임으로 만들어줌 #orient=index를 넣어야 행으로 쭉 나열이 됨 df=pd.DataFrame.from_dict(count, orient='index') df.head() list1=[] for i in range(len(df)): #index를 중심으로 계속 중첩해서 list에 넣는다 list1.append([df.index[i][0],df.index[i][1],df[0][i]]) #pandas 이용해서 df형태로 만들기 df2=pd.DataFrame(list1, columns=["term1","term2","freq"]) #pandas 이용해서 sorting 하기 (디폴트가 오름차순이라서 false 꼭 써줘야 내림차순으로 나옴) df3=df2.sort_values(by=['freq'],ascending=False) df3.head(100)
#추천 참고자료 박건영. 2019. Networkx를 활용한 네트워크 분석 기법 기초 입문 import numpy as np import networkx as nx import operator #np.where는 조건문 만드는 것: (슬라이싱) 빈도가 5개 이상인 것만 잘라내면 1027개가 나온다. (참인 조건의 인덱스 추출) len((np.where(df3['freq']>=5))[0]) G=nx.Graph() for i in range(1027): #print(pair) G.add_edge(df3['term1'][i], df3['term2'][i], weight=int(df3['freq'][i])) # Compute centralities for nodes. # The degree centrality values are normalized by dividing by the maximum possible degree in a simple graph n-1 where n is the number of nodes in G. dgr = nx.degree_centrality(G) btw = nx.betweenness_centrality(G) cls = nx.closeness_centrality(G) # itemgetter(0): key 또는 itemgetter(1): value로 sort key, reverse=True (descending order) sorted_dgr = sorted(dgr.items(), key=operator.itemgetter(1), reverse=True) sorted_btw = sorted(btw.items(), key=operator.itemgetter(1), reverse=True) sorted_cls = sorted(cls.items(), key=operator.itemgetter(1), reverse=True) print("** degree **") for x in range(20): print(sorted_dgr[x]) print("** betweenness **") for x in range(20): print(sorted_btw[x]) print("** closeness **") for x in range(20): print(sorted_cls[x]) #단어끼리 서로 빈도를 세는 데이터셋을 만들었을 때 Gaphi로 시각화하는 것 전단계: graphml 확장자 형식으로 만들기 class MakeGraphml: def make_graphml(self, pair_file, graphml_file): out = open(graphml_file, 'w', encoding = 'utf-8') entity = [] e_dict = {} count = [] for i in range(len(pair_file)): e1 = pair_file.iloc[i,0] e2 = pair_file.iloc[i,1] #frq = ((word_dict[e1], word_dict[e2]), pair.split('\t')[2]) frq = ((e1, e2), pair_file.iloc[i,2]) if frq not in count: count.append(frq) # ((a, b), frq) if e1 not in entity: entity.append(e1) if e2 not in entity: entity.append(e2) print('# terms: %s'% len(entity)) #create e_dict {entity: id} from entity for i, w in enumerate(entity): e_dict[w] = i + 1 # {word: id} out.write( "<?xml version=\"1.0\" encoding=\"UTF-8\"?><graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlnshttp://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">" + "<key id=\"d1\" for=\"edge\" attr.name=\"weight\" attr.type=\"double\"/>" + "<key id=\"d0\" for=\"node\" attr.name=\"label\" attr.type=\"string\"/>" + "<graph id=\"Entity\" edgedefault=\"undirected\">" + "\n") # nodes for i in entity: out.write("<node id=\"" + str(e_dict[i]) +"\">" + "\n") out.write("<data key=\"d0\">" + i + "</data>" + "\n") out.write("</node>") # edges for y in range(len(count)): out.write("<edge source=\"" + str(e_dict[count[y][0][0]]) + "\" target=\"" + str(e_dict[count[y][0][1]]) + "\">" + "\n") out.write("<data key=\"d1\">" + str(count[y][1]) + "</data>" + "\n") #out.write("<edge source=\"" + str(count[y][0][0]) + "\" target=\"" + str(count[y][0][1]) +"\">"+"\n") #out.write("<data key=\"d1\">" + str(count[y][1]) +"</data>"+"\n") out.write("</edge>") out.write("</graph> </graphml>") print('now you can see %s' % graphml_file) #pairs.close() out.close() gm = MakeGraphml() graphml_file = '파일명.graphml' #iloc는 인덱스 index of location 열에서 : 써야 함 (열 전체 보여주려면) gm.make_graphml(df3.iloc[0:1027,:], graphml_file) f.close() |