ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 빈도 분석(frequency analysis)- 영어편
    Text Analysis 2021. 11. 24. 22:33

    *본 게시물은 21-2학기 연세대학교 일반대학원 온라인데이터수집과분석(이상엽 교수님) 수업 내용을 정리한 것입니다.

     

      앞선 포스트들에서 Counter를 사용한 빈도 분석의 예들을 보여드렸었습니다. 이 포스트에서는 보다 체계적이고 본격적인 빈도 분석의 예를 다루고자 합니다. 이번 포스트에서는 영어 text를 원시 말뭉치로 하겠습니다. 

     

    빈도분석의 목적

      빈도분석은 왜하는걸까요? 가장 얻기 쉬운 정보라서? 그럴 수도 있겠지만 빈도분석의 주된 목적은 '주요 키워드 찾기'입니다. 

    '주요 키워드'를 찾는 것이 중요한 이유는 주요한 주제와 연결되기 때문입니다. 즉 빈도분석은 주요 키워드를 통해 주요 주제가 무엇인지 찾고자 할 때 사용하는 분석 기법입니다.

     

    빈도분석의 순서 및 방법

      순서는 '1. 텍스트 준비 -> 2. 전처리 -> 3. 빈도분석'으로 비교적 간단합니다. 전처리를 하는 이유는 불용어가 제거된 특정 품사의 단어를 추출하기 위해서입니다. 빈도분석에는 이 특정 품사 단어 목록이 필요합니다.

      앞선 포스트들에서도 보셨겠지만 빈도분석을 위해서는 Counter 클래스가 필요합니다. 또한 단어의 빈도를 알게 되면 word cloud를 통한 시각화까지 가능합니다.  실제로 예시 코드를 보도록 하겠습니다.

     

    일단 1. 텍스트를 준비합니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import nltk
    from nltk.corpus import stopwords
    import re
    import nltk
    nltk.download('all')
     
    # 1. 텍스트 준비
    with open('nytimes.txt''r', encoding='utf8'as f:
        content = f.read()
    cs

     

      그 다음 2. 전처리를 합니다. 여기서는 지난번 영어 text preprocessing에서 다룬 단계들을 한 큐에 해치울 수 있는 사용자 정의 함수를 만듭니다... ㅎㄷㄷ (단계는 1. 정제, 2. 대소문자화, 3. 토크나이징, 4. POS 태깅 & 5. 원하는 품사 담기, 6.  lemmatization&stemming, 7. 불용어 제거입니다.)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    # 2. 전처리를 한번에 해결할 수 있는 사용자 정의 함수 만들기
     
    def do_En_preprocessing(text, customized_stopwords):
        cleaned_content = re.sub(r'[^\w\d\s]','',text) # 1. 정제;To remove symbols
        cleaned_content = cleaned_content.lower() # 2. 대소문자화: Case conversion, upper -> lower
        word_tokens = nltk.word_tokenize(cleaned_content) # 3. 토크나이징 Tokenization
        tokens_pos = nltk.pos_tag(word_tokens) # 4. 품사태깅: POS tagging
        NN_words = []   # 5. 품사 골라담기 To select nouns
        for word, pos in tokens_pos:
            if 'NN' in pos:
                NN_words.append(word)
                
        wlem = nltk.WordNetLemmatizer()   # 6. Lemmatization
        lemmatized_words = []
        for word in NN_words:
            lemmatized_words.append(wlem.lemmatize(word))
        # 7. 불용어 제거    
        stopwords_list = stopwords.words('english')
        unique_NN_words = set(lemmatized_words)
        final_NN_words = lemmatized_words
        for word in unique_NN_words:
            if word in stopwords_list:
                while word in final_NN_words: 
                    final_NN_words.remove(word)
        
        unique_NN_words1 = set(final_NN_words)
        for word in unique_NN_words1:
            if word in customized_stopwords:
                while word in final_NN_words: 
                    final_NN_words.remove(word)
        
        return final_NN_words
    # 전처리 7단계를 모두 끝낸 text가 리턴되는 함수 완성!
    cs

      이런 사용자 함수 전처리는 다음과 같이 적용합니다. 우선은 사용자 정의 함수의 인자를 잘 맞춰 넣어야 합니다. 그런다면 전처리 결과가 리스트 형식으로 리턴됩니다. 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # 사용자 정의 함수 중 나머지 인자인 customized_stopwords를 정의해줍니다.
    customized_stopwords = ['york''time''news']
     
    # 그 이후로 사용자 정의 함수를 온전하게 적용하면...
    final_words = do_En_preprocessing(content, customized_stopwords)
    # rawtext가 첫번째 인자, 사용자 정의 함수가 두번째 인자로 들어갑니다.
    print(final_words) # 리스트로 리턴됨
    '''
    ['hurray', 'hotblack', 'coffee', ...]
    '''
     
    #단, 워드 클라우드 클래스의 generator는 리스트를 인자로 받을 수 없습니다.
    # 하나의 문자열로 만들어야 함 >> text = ' '.join(final_words)를 사용 
    cs

    위의 결과인 리스트를 문자열로 만드는 코드는 다음과 같습니다.

    1
    2
    3
    4
    5
    6
    7
    # 리스트를 문자열로 만들 때는...
    text = ' '.join(final_words)
    text
    '''
    'hurray hotblack coffee cafe toronto wifi...'
    '''
    # '...'으로 싸여있는 것을 보아 string임을 확인
    cs

     

    3. 빈도분석 & 워드클라우드 만들기

    위에서도 이야기했다시피 빈도분석은 주요 키워드를 통해 주요한 주제를 파악할 수 있게 하는 분석 방법입니다. 우선 Counter를 사용한 빈도분석 방법을 보겠습니다.

     

    1) Counter 사용하여 빈도분석

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # Counter 클래스 불러오기
    from collections import Counter
     
    # 단어별 빈도수 출력
    = Counter(final_words)
    print(c)
    '''
    Counter({'health': 11, 'people': 11, 'researcher': 7,..})
    '''
     
    # 빈도수 상위 10위 단어 표출
    c.most_common(10)
    '''
    [('health', 11),
     ('people', 11),
     ('researcher', 7),
     ('study', 6), ..]
    ''' 
    cs

     

    2) 워드클라우드를 통한 시각화

      데이터 사이언스나 자연어 처리 논문을 보면 워드 클라우드가 심심치 않게 나옵니다. 워드클라우드는 비단 직사각형 모양의 시각화 뿐 아니라, 마스킹을 통해 다양한 도안으로 시각화가 가능합니다 ㅎ_ㅎ

     

      우선은 일반 직사각형으로 시각화하는 코드를 보여드리겠습니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    !pip intall wordCloud
     
    from wordcloud import WordCloud
    import matplotlib.pyplot as plt
    #워드 클라우드 클래스의 generator는 리스트를 인자로 받을 수 없음 
    total_words = ' '.join(final_words)# 하나의 문자열로 만들어야 함 >> text = ' '.join(final_words)를 사용(띄어쓰기로 연결)
     
    # print(total_words)
     
    wordcloud = WordCloud(max_font_size=200, width=1500, height=1000, background_color='pink'#객체 만들기
    # 객체 안에는 주로 주요한 파라미터가 존재 
    wordcloud.generate(total_words) #generate function은 문자열을 받음
    plt.figure()
    plt.imshow(wordcloud, interpolation='bilinear')
    plt.axis("off")
    plt.show()
    wordcloud.to_file("nytimes.png"# to save at the working folder # 지금 작업하는 폴더에 이미지 파일로 저장 가능 
    cs

      혹은 마스킹으로 다양한 도형들을 도안으로 사용할 수도 있습니다. 이떄, 단어로 채우고자 하는 부분은 반드시 검은색, 나머지 부분은 흰색이어야 합니다. 

     

    동그라미

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 동그라미 도안으로 마스킹
     
    import numpy as np
    x, y = np.ogrid[:300, :300]
     
    mask = (x - 150** 2 + (y - 150** 2 > 130 ** 2
    mask = 255 * mask.astype(int)
     
    wc = WordCloud(background_color='white', repeat=True, mask=mask)
    wc.generate(total_words)
    plt.axis("off")
    plt.imshow(wc, interpolation="bilinear")
    plt.show()
    wc.to_file("circle.png"# 동그라미를 도안으로 사여 시각화
    cs

     

    앨리스

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    # 앨리스를 도안으로 하기(!)
     
    from os import path
    from PIL import Image
    import numpy as np
    import matplotlib.pyplot as plt
     
    from wordcloud import WordCloud
     
    # 이미지 마스킹 시 흑/백 이미지.png로 준비해야 함 
    alice_mask = np.array(Image.open("alice_mask.png"))
    # Image.open 시 np.array로 가져오게 됨
    #이미지는 그러나 pixel로 이루어짐 0~255 개로 색을 표현 
    #흑백 이미지의 경우 0=검은색 ~ 255= 흰색 
    #워드클라우드는 애매모호한 회색까지를 포함하여 시각화 진행
    # 즉 픽셀에 저장된 수가 1 이상이면 무조건 작업
    # 때문에 지나치게 복잡한 도안은 시각화가 되지 않음: ex. 체크판 무늬; 
    wc1 = WordCloud(background_color="white", width=674, height=643, mask=alice_mask)
     
    # generate word cloud
    wc1.generate(total_words)
     
    # store to file
    wc1.to_file("alice.png")
     
    plt.figure()
    plt.imshow(wc1)
    plt.axis("off")
    plt.show()
    cs

     

    트위터 짹짹이

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    # 트위터 새 모양으로 마스킹
     
    from os import path
    from PIL import Image
    import numpy as np
    import matplotlib.pyplot as plt
     
    from wordcloud import WordCloud
     
    twitter_mask = np.array(Image.open("twitter.png"))
    twitter_mask[twitter_mask>0]=255 #회색을 처리하기 위한 코드
    # 회색은 흰색으로 반환 후 시각화
     
    wc1 = WordCloud(background_color="white", width=674, height=643, mask=twitter_mask)
     
    # generate word cloud
    wc1.generate(total_words)
     
    # store to file
    wc1.to_file("twitter_wc.png")
     
    plt.figure()
    plt.imshow(wc1)
    plt.axis("off")
    plt.show()
    cs

     

     

     

    'Text Analysis' 카테고리의 다른 글

    Text 전처리(preprocessing)- korean 한글편  (0) 2021.11.24
    Text 전처리(preprocessing)- english 영어편  (0) 2021.11.24
    Text Analysis의 시작  (0) 2021.11.23

    댓글

Designed by Tistory.