'pandas DataFrame에 tokenization 함수 적용하기'에 해당되는 글 1건

  1. 2022.08.01 [Python] 텍스트 데이터 전처리 및 토큰화 (Tokenization)

이번 포스팅에서는 Python을 사용해서 

 

(1) 텍스트 데이터 전처리 (text data pre-processing)

(2) 토큰화 (tokenization)

 

하는 방법을 소개하겠습니다. 

 

 

(1) 텍스트 데이터 전처리 (text data pre-processing)

 

텍스트 데이터 전처리를 하는데는 (a) Python의 텍스트 처리 내장 메소드 (Python built-in methods)와 (b) 정규 표현식 매칭 연산(regular expression matching operations)을 제공하는 Python re 패키지를 사용하겠습니다. re 패키지는 Python을 설치할 때 디폴트로 같이 설치가 되므로 별도로 설치할 필요는 없습니다. 

 

예제로 사용할 Input 텍스트는 인터넷쇼핑몰의 고객별 거래내역에 있는 구매 품목 텍스트 데이터이며, Output 은 텍스트 전처리 후의 고객별 구매 품목의 리스트입니다. 

 

예) Input: '**[세일]** 말티즈 강아지사료 습식 소프트 신 3종 15Kg 39,000원!!...외5건'

예) Output: [말티즈, 강아지사료, 습식, 소프트]

 

[ 텍스트 데이터 전처리 절차 ]

    (1-1) [], (), {}, <> 괄호와 괄호 안 문자 제거하기

    (1-2) '...외', '...총' 제거하기

    (1-3) 특수문자, 숫자 제거

    (1-4) 단위 제거: cm, km, etc.

    (1-5) 공백 기준으로 분할하기

    (1-6) 글자 1개만 있으면 제외하기

    (1-7) 텍스트 데이터 전처리 사용자 정의함수(User Defined Function) 정의 

    (1-8) pandas DataFrame의 텍스트 칼럼에 데이터 전처리 사용자 정의함수 적용

 

 

(1-1) [], (), {}, <> 괄호와 괄호 안 문자 제거하기

 

Python의 정규 표현식(regular expression)을 다루는 re 패키지를 사용해서 다양한 형태의 괄호와 괄호안의 문자를 매칭한 후에 '' 로 대체함으로써 결과적으로 제거하였습니다. re.sub() 는 pattern 과 매치되는 문자열을 repl 의 문자열로 대체를 시켜줍니다. 

 

정규표현식에서 문자 클래스를 만드는 메타 문자인 [ ] 로 만들어지는 정규표현식은 [ ]사이에 들어가는 문자 중 어느 한개라도 매치가 되면 매치를 시켜줍니다. 가령, [abc] 의 경우 'a', 'b', 'c' 중에서 어느 하나의 문자라도 매치가 되면 매치가 되는 것으로 간주합니다. 

 

## Python Regular expression operations
import re

## sample text
s = '**[세일]** 말티즈 강아지사료 습식 소프트 신 3종 15Kg 39,000원!!...외5건'


## (1-1) [], (), {}, <> 괄호와 괄호 안 문자 제거하기
pattern = r'\([^)]*\)'  # ()
s = re.sub(pattern=pattern, repl='', string=s)

pattern = r'\[[^)]*\]'  # []
s = re.sub(pattern=pattern, repl='', string=s)

pattern = r'\<[^)]*\>'  # <>
s = re.sub(pattern=pattern, repl='', string=s)

pattern = r'\{[^)]*\}'  # {}
s = re.sub(pattern=pattern, repl='', string=s)

print(s)
[Out] 
# **** 말티즈 강아지사료 습식 소프트 신 3종 15Kg 39,000원!!...외5건

 

 

 

(1-2) '...외', '...총' 제거하기

 

Python의 내장 문자열 메소드인 replace() 를 사용해서 '...외', '...총' 을 ' ' 로 대체함으로써 제거하였습니다. 

 

## (1-2) '...외', '...총' 제거하기
s = s.replace('...외', ' ')
s = s.replace('...총', ' ')

print(s)
[Out]
# **** 말티즈 강아지사료 습식 소프트 신 3종 15Kg 39,000원!! 5건

 

 

 

(1-3) 특수문자, 숫자 제거

 

정규표현식에서 하이픈(-)은 from ~ to 의 범위를 나타냅니다. [a-zA-Z] 는 소문자와 대문자 영어 모두를 의미하며, [가-힣] 은 한글 전체를 의미합니다. 

 

정규표현식에서 [^] 는 not 의 의미이며, 아래의 [^a-zA-Z가-힣] 은 앞에 '^' 가 붙었으므로 영어와 한글이 아닌(not, ^) 문자, 즉 특수문자와 숫자와 매칭이 됩니다. 

 

## (1-3) 특수문자, 숫자 제거
pattern = r'[^a-zA-Z가-힣]'
s = re.sub(pattern=pattern, repl=' ', string=s)

print(s)
[Out] 
# 말티즈 강아지사료 습식 소프트 신  종   Kg       원    건

 

 

 

(1-4) 단위 제거: cm, km, etc.

 

## (1-4) 단위 제거: cm, km, etc.
units = ['mm', 'cm', 'km', 'ml', 'kg', 'g']
for unit in units:
    s = s.lower() # 대문자를 소문자로 변환
    s = s.replace(unit, '')
    
print(s)
[Out] 
# 말티즈 강아지사료 습식 소프트 신  종          원    건

 

 

 

(1-5) 공백 기준으로 분할하기

 

Python 내장형 문자열 메소드인 split() 을 사용해서 공백(space)을 기준으로 문자열을 분할하였습니다. 

 

## (1-5) 공백 기준으로 분할하기
s_split = s.split()

print(s_split)
[Out] 
# ['말티즈', '강아지사료', '습식', '소프트', '신', '종', '원', '건']

 

 

 

(1-6) 글자 1개만 있으면 제외하기

 

글자 길이가 1 보다 큰 (len(word) != 1) 글자만 s_list 의 리스트에 계속 추가(append) 하였습니다. 

 

## (1-6) 글자 1개만 있으면 제외하기
s_list = []
for word in s_split:
    if len(word) !=1:
        s_list.append(word)
        
print(s_list)
[Out] 
# ['말티즈', '강아지사료', '습식', '소프트']

 

 

 

(1-7) 텍스트 데이터 전처리 사용자 정의함수(User Defined Function) 정의 

 

위의 (1-1) ~ (1-6) 까지의 텍스트 전처리 과정을 아래에 사용자 정의함수로 정의하였습니다. 문자열 s 를 input으로 받아서 텍스트 전처리 후에 s_list 의 단어들을 분할해서 모아놓은 리스트를 반환합니다. 

 

## 텍스트 전처리 사용자 정의함수(UDF of text pre-processing)
def text_preprocessor(s):
    import re
    
    ## (1) [], (), {}, <> 괄호와 괄호 안 문자 제거하기
    pattern = r'\([^)]*\)'  # ()
    s = re.sub(pattern=pattern, repl='', string=s)
    
    pattern = r'\[[^)]*\]'  # []
    s = re.sub(pattern=pattern, repl='', string=s)
    
    pattern = r'\<[^)]*\>'  # <>
    s = re.sub(pattern=pattern, repl='', string=s)
    
    pattern = r'\{[^)]*\}'  # {}
    s = re.sub(pattern=pattern, repl='', string=s)
    
    ## (2) '...외', '...총' 제거하기
    s = s.replace('...외', ' ')
    s = s.replace('...총', ' ')
    
    ## (3) 특수문자 제거
    pattern = r'[^a-zA-Z가-힣]'
    s = re.sub(pattern=pattern, repl=' ', string=s)
    
    ## (4) 단위 제거: cm, km, etc.
    units = ['mm', 'cm', 'km', 'ml', 'kg', 'g']
    for unit in units:
        s = s.lower() # 대문자를 소문자로 변환
        s = s.replace(unit, '')
        
    # (5) 공백 기준으로 분할하기
    s_split = s.split()
    
    # (6) 글자 1개만 있으면 제외하기
    s_list = []
    for word in s_split:
        if len(word) !=1:
            s_list.append(word)
            
    return s_list
    

## sample text
s = '**[세일]** 말티즈 강아지사료 습식 소프트 신 3종 15Kg 39,000원!!...외5건'

## apply the UDF above
s_list = text_preprocessor(s)
print(s_list)
[Out] 
# ['말티즈', '강아지사료', '습식', '소프트']

 

 

 

(1-8) pandas DataFrame의 텍스트 칼럼에 데이터 전처리 사용자정의함수 적용

 

pandas DataFrame에 위의 (1-7) 텍스트 전처리 사용자 정의함수를 적용하기 위해서는 apply() 와 lambda function 을 사용합니다. 

 

## pandas DataFrame
import pandas as pd

s1 = '**[세일] 몰티즈 강아지사료 습식 소프트 신 3종 15Kg 39,000원!!...외5건'
s2 = '[시크루즈] 50%+추가20%/여름신상 루즈핏 롱원피스/상하세트/점프슈트...외3건'
s3 = '올챌린지 KF94 마스크 100매 국내생산 여름용 황사 화이트...총2건'
s4 = '[최대혜택가] ##하림 용가리치킨 300gX3봉 외 닭가슴살/튀김 골라담기...외12건'
s5 = '[20%+15%] 종아리알 타파! 무로 요가링/마사지릴/압박스타킹/마사지볼...외4종'

df = pd.DataFrame({
    'id': [1, 2, 3, 4, 5], 
    'items': [s1, s2, s3, s4, s5]
})

print(df)
[Out]
#    id                                              items
# 0   1  **[세일] 몰티즈 강아지사료 습식 소프트 신 3종 15Kg 39,000원!!...외5건
# 1   2     [시크루즈] 50%+추가20%/여름신상 루즈핏 롱원피스/상하세트/점프슈트...외3건
# 2   3           올챌린지 KF94 마스크 100매 국내생산 여름용 황사 화이트...총2건
# 3   4   [최대혜택가] ##하림 용가리치킨 300gX3봉 외 닭가슴살/튀김 골라담기...외12건
# 4   5    [20%+15%] 종아리알 타파! 무로 요가링/마사지릴/압박스타킹/마사지볼...외4종


## Apply the text preprocessing UDF using apply() and lambda function
df['items_list'] = df['items'].apply(lambda s: text_preprocessor(s))


print(df['items'])
print('-------------'*5)
print(df['items_list'])
[Out]
# 0    **[세일] 몰티즈 강아지사료 습식 소프트 신 3종 15Kg 39,000원!!...외5건
# 1       [시크루즈] 50%+추가20%/여름신상 루즈핏 롱원피스/상하세트/점프슈트...외3건
# 2             올챌린지 KF94 마스크 100매 국내생산 여름용 황사 화이트...총2건
# 3     [최대혜택가] ##하림 용가리치킨 300gX3봉 외 닭가슴살/튀김 골라담기...외12건
# 4      [20%+15%] 종아리알 타파! 무로 요가링/마사지릴/압박스타킹/마사지볼...외4종
# Name: items, dtype: object
# -----------------------------------------------------------------
# 0                     [몰티즈, 강아지사료, 습식, 소프트]
# 1         [추가, 여름신상, 루즈핏, 롱원피스, 상하세트, 점프슈트]
# 2       [올챌린지, kf, 마스크, 국내생산, 여름용, 황사, 화이트]
# 3               [하림, 용가리치킨, 닭가슴살, 튀김, 골라담기]
# 4    [종아리알, 타파, 무로, 요가링, 마사지릴, 압박스타킹, 마사지볼]
# Name: items_list, dtype: object

 

 

 

위에 Jupyter Notebook 에서 pandas DataFrame을 출력한 결과가 중앙 정렬로 되어있어서 보기가 불편한데요, 아래처럼 좌측 정렬 (left alignment) 을 해서 보기에 편하도록 해보았습니다. 

 

## align text of pandas DataFrame to left in Jupyter Notebook
dfStyler = df.style.set_properties(**{'text-align': 'left'})
dfStyler.set_table_styles([dict(selector='th', props=[('text-align', 'left')])])

text preprocessing using regular expressions

 

 

 

(2) 토큰화 (tokenization)

 

토큰화(Tokenization)는 말뭉치(Corpus)를 토큰이라고 불리는 단어 또는 문장으로 나누는 것을 말합니다. 이러한 토큰은 문맥(Context)을 이해하거나 NLP에 대한 모델을 개발하는 데 사용됩니다. 

 

POS 태킹 (Part-of-Speech Tagging) 은 널리 사용되는 자연어 처리 프로세스로, 단어의 정의와 문맥에 따라 언어의 특정 부분에 대응하여 텍스트(corpus)의 단어를 분류하는 것을 말합니다.

 

아래 코드는 위 (1)번의 텍스트 전처리에 이어서, 띄어쓰기가 제대로 되지 않아서 붙어 있는 단어들을, Python KoNLpy 패키지를 사용해서 형태소 분석의 명사를 기준으로 단어 토근화를 한 것입니다. ((2)번 words_tokonizer() UDF 안에 (1)번 text_preprocessor() UDF가 포함되어 있으며, 순차적으로 수행됩니다.)

 

KoNLpy 패키지는 Python으로 한국어 자연어 처리(NLP) 을 할 수 있게 해주는 패키지입니다. 그리고 Kkma 는 서울대학교의 IDS 랩에서 JAVA로 개발한 형태소 분석기(morphological analyzer)입니다.  

 

## insatll konlpy if it is not istalled yet
# ! pip install konlpy


## KoNLpy : NLP of the Korean language
## reference ==> https://konlpy.org/en/latest/
## Kkma is a morphological analyzer 
## and natural language processing system written in Java, 
## developed by the Intelligent Data Systems (IDS) Laboratory at SNU.
from konlpy.tag import Kkma


## define words tokenizer UDF
def words_tokonizer(text):
    from konlpy.tag import Kkma # NLP of the Korean language
    kkma = Kkma()
    
    words = []
    
    # Text preprocessing using the UDF above
    s_list = text_preprocessor(text)
    
    # POS tagging
    for s in s_list:
        words_ = kkma.pos(s)   
        
        # NNG indexing
        for word in words_:
            if word[1] == 'NNG':
                words.append(word[0])
            
    return words
    
    
## apply the UDF above as an example
words_tokonizer('강아지사료')
[Out] ['강아지', '사료']


words_tokonizer('상하세트')
[Out] ['상하', '세트']

 

 

위의 (2) words_tokenizer() UDF를 pandas DataFrame에 적용하기 위해서 apply() 함수와 lambda function 을 사용하면 됩니다. 

 

## apply the text tokenization UDF to pandas DataFrame using apply() and lambda function
df['items'].apply(lambda text: words_tokonizer(text))

[Out]
# 0 [몰티즈, 강아지, 사료, 습식, 소프트]
# 1 [추가, 여름, 신상, 루즈, 핏, 원피스, 상하, 세트, 점프, 슈트]
# 2 [챌린지, 마스크, 국내, 생산, 여름, 황사, 화이트]
# 3 [하림, 용가리, 치킨, 닭, 가슴살, 튀김]
# 4 [종아리, 타파, 무로, 요가, 링, 마사지, 압박, 스타, 킹, 마사지]
# Name: items, dtype: object

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요! :-)

 

728x90
반응형
Posted by Rfriend
,