def test_iterator_NotImplementedError(self): keyword_processor = KeywordProcessor() keyword_processor.add_keyword('j2ee', 'Java') keyword_processor.add_keyword('colour', 'color') keyword_processor.get_all_keywords() with pytest.raises(NotImplementedError): for value in keyword_processor: pass
def test_get_all_keywords(self): keyword_processor = KeywordProcessor() keyword_processor.add_keyword('j2ee', 'Java') keyword_processor.add_keyword('colour', 'color') keyword_processor.get_all_keywords() self.assertEqual(keyword_processor.get_all_keywords(), { 'colour': 'color', 'j2ee': 'Java' }, "get_all_keywords didn't match expected results.")
# output: True # 获取某个词的标准词 keyword_processor.get_keyword('j2ee') # output: Java keyword_processor['colour'] = 'color' print(keyword_processor['colour']) # output: color keyword_processor.get_keyword('colour') # Out[31]: 'color' # 获取字典中的所有关键词 keyword_processor = KeywordProcessor() keyword_processor.add_keyword('j2ee', 'Java') keyword_processor.add_keyword('colour', 'color') keyword_processor.get_all_keywords() # output: {'colour': 'color', 'j2ee': 'Java'} # 除\w [A-Za-z0-9_]之外的任何字符,都认为是一个单词的边界 keyword_processor = KeywordProcessor() keyword_processor.add_keyword('Big Apple') print(keyword_processor.extract_keywords('I love Big Apple/Bay Area.')) # ['Big Apple'] print(keyword_processor.extract_keywords('I love Big Apple_Bay Area.')) # [] print(keyword_processor.extract_keywords('I love Big Apple2Bay Area.')) # [] # 设置或添加字符作为单词字符的一部分 keyword_processor.add_non_word_boundary('/') print(keyword_processor.extract_keywords('I love Big Apple/Bay Area.'))
def select_best_keywords(metadata_table): table_to_process = metadata_table[["pr_title", "pr_abstract"]] table_to_process["pr_title"] = table_to_process["pr_title"].apply( lambda x: remove_stop_words(x)) table_to_process["pr_abstract"] = table_to_process["pr_abstract"].apply( lambda x: remove_stop_words(x)) print("Text Data after removing of stop-words") print(table_to_process) words_corpus = get_words_corpus(table_to_process) print(len(words_corpus)) dist = nltk.FreqDist( words_corpus) #Creating a distribution of words' frequencies grams = dist.most_common(1000) #Obtaining the most frequent words bigrams = nltk.collocations.BigramAssocMeasures() trigrams = nltk.collocations.TrigramAssocMeasures() bigramFinder = nltk.collocations.BigramCollocationFinder.from_words( words_corpus) trigramFinder = nltk.collocations.TrigramCollocationFinder.from_words( words_corpus) print("Showing first", 2000, "top-freqent words in the corpus") grams = pd.DataFrame( grams ) #Building data table to represent selected by POS tagger word features grams.index = range(1, len(grams) + 1) grams.columns = ["Word", "Frequency"] print(grams) bi_filter = 7 print( "Showing bigrams in the corpus found by Pointwise Mutual Information method" ) print("Applying frequency filter: a bigramm occurs more than", bi_filter, "times") bigramFinder.apply_freq_filter(bi_filter) bigramPMITable = pd.DataFrame(list(bigramFinder.score_ngrams(bigrams.pmi)), columns=['bigram', 'PMI']).sort_values(by='PMI', ascending=False) bigramPMITable["bigram"] = bigramPMITable["bigram"].apply( lambda x: ' '.join(x)) print(bigramPMITable) tri_filter = 5 print( "Showing trigrams in the corpus found by Pointwise Mutual Information method" ) print("Applying frequency filter: a trigramm occurs more than", tri_filter, "times") trigramFinder.apply_freq_filter(tri_filter) trigramPMITable = pd.DataFrame( list(trigramFinder.score_ngrams(trigrams.pmi)), columns=['trigram', 'PMI']).sort_values(by='PMI', ascending=False) trigramPMITable["trigram"] = trigramPMITable["trigram"].apply( lambda x: ' '.join(x)) print(trigramPMITable) gram_dict = grams.set_index('Word').T.to_dict('list') bigramPMIDict = bigramPMITable.set_index('bigram').T.to_dict('list') trigramPMIDict = trigramPMITable.set_index('trigram').T.to_dict('list') keyword_processor = KeywordProcessor() textrank_keyword_processor = KeywordProcessor() gram_dict.update(bigramPMIDict) bigramPMIDict.update(trigramPMIDict) # print(gram_dict) print( "Extracting keywords from texts using Pointwise Mutual Information method and TextRank" ) text_rank_key_words = dict() for i in range(0, len(table_to_process)): sentences = table_to_process.loc[i, "pr_abstract"] if sentences != None: keywords = get_keywords_by_textrank(sentences) if keywords != None: text_rank_key_words.update(keywords) print("Text", i, "- Done") for keyword in gram_dict.keys(): parts = keyword.split() parts = "_".join(parts) keyword_processor.add_keyword(keyword, parts) for keyword in text_rank_key_words.keys(): parts = keyword.split() parts = "_".join(parts) textrank_keyword_processor.add_keyword(keyword, parts) print("Keywords amount gathered using PMI method") print(len(keyword_processor.get_all_keywords())) print("Keywords amount gathered using TextRank method") print(len(textrank_keyword_processor.get_all_keywords())) table_to_process["pr_abstract"] = table_to_process["pr_abstract"].apply( lambda x: merge_two_keywords_methods(x, textrank_keyword_processor, keyword_processor)) for i in range(0, len(table_to_process)): metadata_table.loc[i, "pr_title"] = table_to_process.loc[i, "pr_title"] metadata_table.loc[i, "pr_abstract"] = table_to_process.loc[i, "pr_abstract"] print( "Comparison of Text Data after Keywords Extraction using Pointwise Mutual Information method and TextRank" ) print(metadata_table[["title", "pr_title", "abstract", "pr_abstract"]]) print("Extracting keywords from texts using TF/IDF") dataset = [] for i in range(0, len(table_to_process["pr_abstract"])): sentences = table_to_process.loc[i, "pr_abstract"] if sentences != None: sentences = " ".join(sentences) dataset.append(sentences) tfIdfVectorizer = TfidfVectorizer(use_idf=True) tfIdf = tfIdfVectorizer.fit_transform(dataset) index = 0 for i in range(0, len(metadata_table)): if table_to_process.loc[i, "pr_abstract"] == None: continue metadata_table.loc[i, "pr_abstract"] = retain_best_tf_idf_keywords( table_to_process.loc[i, "pr_abstract"], index, tfIdf, tfIdfVectorizer) index += 1 return metadata_table
def Delete_StandardStopwords(username, prname): # 1차 불용어 처리 (불용어 사전을 새로 수정하고 만들어야 합니다.) import re, os from tqdm import tqdm from flashtext import KeywordProcessor from utils import Read_Arg_, Read_Sheet_, import_dataframe, export_dataframe kp = KeywordProcessor() tqdm.pandas() if (username == "") & (prname == ""): input_directory = "" # Non-창민버전 else: input_directory = "/".join([username, prname]) # Non-창민버전 ref, input_, output_ = Read_Arg_( username, prname, "Delete_StandardStopwords" ) # Read_Arg를 통해 참조파일, input파일, output파일을 불러옵니다. # 이 때 ref는 "JDic_BizStopwords(경영불용어사전)"시트를, # input파일은 메세지 csv파일의 이름, # output은 처리 후 내보낼 메세지 csv파일의 이름입니다. Sym2Remain = Read_Sheet_(username, prname, "SymbolsDictionary") Clean = Read_Sheet_(username, prname, ref) # Clean이라는 변수에 Read_Sheet를 통해 # "JDic_BizStopwords(경영불용어사전)"시트를 불러옵니다. Clean.columns = Clean.iloc[0] Clean = Clean[1:] Clean["unit_length"] = Clean["word"].apply( lambda x: len(x)) # 이 때 하나의 이슈는 표현의 길이에 따른 나열 순서입니다. # (https://greeksharifa.github.io/정규표현식(re)/2018/07/22/regex-usage-03-basic/) # 만약 "에게"와 "에게서"를 예시로 들 떄, # 정규식 인자로 "에게"가 "에게서"보다 먼저 나열될 경우, # 메세지에서 "에게"에 대한 데이터를 먼저 찾으므로 # 실제로 메세지에서 "에게서" 라고 표현되었던 데이터가 # "에게"로 인해 "서"만으로 남게됩니다. # 따라서 위 방법을 사용하게 될 경우, # 불용어 사전의 칼럼으로 unit_length를 두고 # 내림차순으로 정렬하는 것이 바람직해 보입니다. Sym2Remain_np = Sym2Remain.fillna("").to_numpy(dtype=list) all_V = list(map(lambda x: [i for i in x if i != ""], Sym2Remain_np)) # all_V라는 변수에 lemma에 있는 데이터들을 전부 가져옵니다. print(all_V) # 이 때 all_V의 형태는 다음과 같습니다. # [[기준단어 a, 변형단어 a-1, 변형단어 a-2,... ], # [기준단어 b, 변형단어 b-1, 변형단어 b-2,... ], # ... ] for case in all_V: standardised = case[1] for keyword in case[0]: kp.add_keyword(keyword, standardised) print(kp.get_all_keywords()) Clean = Clean.sort_values( by="unit_length", ascending=False) # unit_length열 기준으로 내림차순으로 정렬해주고 최신화합니다. Clean = Clean[~Clean["word"].duplicated()] # 혹시모를 중복 word를 제거합니다. # symbol = set(Clean.loc[Clean["class"] == "s", "word"]) # 기호는 Clean 데이터 프레임에서 # # "class" 컬럼이 s인 것들의 "word"컬럼을 리스트화한 것입니다. # symbol = str(symbol).replace("{", "").replace("}", "").replace(", ''", "").replace(", ", "|").replace("'", "") # print(symbol) characters = set(Clean.loc[Clean["class"] == "c", "word"]) # 문자는 Clean 데이터 프레임에서 # "class" 컬럼이 c인 것들의 "word"컬럼을 리스트화한 것입니다. characters = str(characters).replace("{", "").replace("}", "").replace( ", ''", "").replace(", ", "|").replace("'", "") # 정규표현식을 사용하기 위한 작업입니다. # 본디, JDic_Clean은 ["물론", "무엇", "무슨" …] 처럼 리스트의 형태를 취합니다. # 정규표현식을 조작하게끔 하는 라이브러리 re는 인자로 문자열을 받습니다. # 따라서 리스트를 문자열로 바꿔줍니다. ( str(JDic_Clean) ) # 또한, 정규식에는 .sub 메소드가 있는데, # 이는 세번째 인자(데이터)에서 첫번째 인자(특정 표현)를 발견하면 # 두번째 인자로 바꿔주는 메소드입니다. # 아래에서 item(메세지 데이터의 각 행에 해당하는 데이터) 데이터에서 # 불용어사전에 등록된 표현을 찾아 공백으로 바꿔주고자 합니다. # 이 때, 불용어 사전에 등록된 단어를 하나하나 바꿔주기 보다, # or식( | )을 써서 한번에 lookup하고자 합니다. # 그러기 위해서는 정규식의 인자에 들어가야할 형태는 다음과 같습니다. # "표현 1"|"표현 2"|"표현3"|…" # 더욱이 "ㅜ" 같은경우 "ㅜㅜ"로 메세지에서 발견될 수 있습니다. # 이는 정규식 내 +를 넣어주면 해결됩니다. # +는 해당표현이 1번이상 반복되는 경우를 뜻합니다. # 해당표현 바로 뒤에 +를 써줘 정규식에 넣어줘야 합니다. # 따라서 위 Clean_Candidates에는 다음과 같이 형태가 이루어져 있습니다. # "표현 1 +"|"표현 2 +"|"표현 3 +"|... # def save_symbol(item): # lemmatize라는 함수를 정의합니다. # input = item # while True: # input_revised = kp.replace_keywords(input) #input문장을 replace시켜준 후 item_replaced 변수에 저장 # if input == input_revised: #이전 문장과 수정 후 문장이 같다면 더이상 고칠게 없다는 의미이므로 반복문 탈출 # break # else: # 이전 문장과 다르다면 바꿔줘야할 것이 있었다는 소리이므로 계속 진행. item_revised를 다시 이전의 값을 뜻하는 input으로 변경 # input = input_revised # pass # return input_revised def save_symbol2(item): # lemmatize라는 함수를 정의합니다. (무식 버전) item_revised = item for i in range(len(Sym2Remain["decode"])): item_revised = item_revised.replace( Sym2Remain.iloc[i]["decode"], " " + Sym2Remain.iloc[i]["Encode"] + " ") return item_revised # def Clean_symbol(item): # Clean_stopwords라는 사용자정의함수를 정의합니다. # item_edited = re.sub(symbol, " ", item) # 이는 정규표현식을 통해 item(input_Message의 각행의 데이터)에 대해 # # Clean_candidates에 해당하는 패턴이 나올 시 " "(공백)으로 치환해주는 함수입니다. # item_edited = " ".join(item_edited.split()) # 다중공백도 제거해줍니다. # return item_edited # 이 함수의 리턴값을 치환된 데이터로 최신화된 데이터로 내보내도록 합니다. # def add_space_for_symbol(item): # not_words = list(filter(bool, list(set(re.compile("[^\s*\w*\s*]*").findall(item))))) # for end in not_words: # 메세지의 한 행에서 있는 not_words리스트 요소마다 # item = item.replace(end," "+end) # replace메소드를 통해 스페이스를 첨가해줍니다. # return item def Clean_char(item): # Clean_stopwords라는 사용자정의함수를 정의합니다. item_edited = re.sub( characters, " ", item) # 이는 정규표현식을 통해 item(input_Message의 각행의 데이터)에 대해 # Clean_candidates에 해당하는 패턴이 나올 시 " "(공백)으로 치환해주는 함수입니다. item_edited = " ".join(item_edited.split()) # 다중공백도 제거해줍니다. return item_edited # 이 함수의 리턴값을 치환된 데이터로 최신화된 데이터로 내보내도록 합니다. def Clean_leftover_symbols(item): item_edited = re.sub("[^\w\s]", "", item) item_edited = " ".join(item_edited.split()) # 다중공백도 제거해줍니다. return item_edited input_name = os.path.join(input_directory, input_) input_Message = import_dataframe(input_name) input_Message = input_Message[ input_Message["contents"].notna()] # input Message에 있을 결측치(빈칸)을 제거합니다. input_Message["contents"] = input_Message["contents"].progress_apply( save_symbol2) #input_Message["contents"] = input_Message["contents"].progress_apply(Clean_symbol) # Clean_stopwords를 .apply메소드를 통해 적용시킵니다. # input_Message["contents"] = input_Message["contents"].progress_apply(add_space_for_symbol) #살릴 기호들 앞에 스페이스를 첨가해줍니다. input_Message["contents"] = input_Message["contents"].progress_apply( Clean_char) # Clean_stopwords를 .apply메소드를 통해 적용시킵니다. input_Message["contents"] = input_Message["contents"].progress_apply( Clean_leftover_symbols) output_name = os.path.join(input_directory, output_) export_dataframe(input_Message, output_name) return input_Message # Delete_Characters의 리턴값으로 최신화된 데이터프레임으로 내보내도록 합니다.
# output: True # 获取某个词的标准词 keyword_processor.get_keyword('j2ee') # output: Java keyword_processor['colour'] = 'color' print(keyword_processor['colour']) # output: color keyword_processor.get_keyword('colour') # Out[31]: 'color' # 获取字典中的所有关键词 keyword_processor = KeywordProcessor() keyword_processor.add_keyword('j2ee', 'Java') keyword_processor.add_keyword('colour', 'color') keyword_processor.get_all_keywords() # output: {'colour': 'color', 'j2ee': 'Java'} # 除\w [A-Za-z0-9_]之外的任何字符,都认为是一个单词的边界 keyword_processor = KeywordProcessor() keyword_processor.add_keyword('Big Apple') print(keyword_processor.extract_keywords('I love Big Apple/Bay Area.')) # ['Big Apple'] print(keyword_processor.extract_keywords('I love Big Apple_Bay Area.')) # [] print(keyword_processor.extract_keywords('I love Big Apple2Bay Area.')) # [] # 设置或添加字符作为单词字符的一部分 keyword_processor.add_non_word_boundary('/') print(keyword_processor.extract_keywords('I love Big Apple/Bay Area.'))
from flashtext import KeywordProcessor key_word = KeywordProcessor() dict = {'teste': ['teste.nes', 'teste1.nes' , 'teste teste.nes']} arq = 'teste' print(key_word.get_all_keywords(dict))