[텍스트 마이닝] 데이터 전처리

Updated:

3. 텍스트 데이터

3.1 정규 표현식

기호
의미
* 바로 앞에 있는 문자, 하위 표현식이 0번 이상 반복됨.
+ 바로 앞에 있는 문자, 하위 표현식이 1번 이상 반복됨.
[] 대괄호 안에 있는 문자 중 하나가 나타남.
() 괄호 안의 정규식을 하위 표현식 그룹으로 만듦.
정규 표현식을 평가할 때는 하위 표현식이 가장 먼저 평가됨.
. 어떠한 형태든 문자 1자를 나타냄.
^ 바로 뒤에 있는 문자, 하위 표현식이 문자열 맨 앞에 나타남.
$ 바로 뒤에 있는 문자, 하위 표현식이 문자열 맨 뒤에 나타남.
{m} 바로 뒤에 있는 문자, 하위 표현식이 m회 반복됨.
{m,n} 바로 뒤에 있는 문자, 하위 표현식이 m번 이상, n번 이하 나타남.
| 분리된 문자, 문자열, 하위 표현식 중 하나가 나타남(or와 같은 용법).
[^] 대괄호 안에 있는 문자를 제외한 문자가 나타남.

정규표현식은 re 라이브러리를 통해 구현할 수 있다.

  • compile : 정규표현식 패턴 지정함수
  • findall : 정규표현식에 부합하는 문자열을 찾는 함수

[예제1] a가 1회이상, b가 0회 이상 나오는 문자열을 찾아라.

import re
r = re.compile("a+b*")
r.findall("aaaa, cc, bbbb, aabbb")

[‘aaaa’, ‘aabbb’]


[예제2] 대문자로 구성된 문자열을 찾아라.

r = re.compile("[A-Z]+")
r.findall("HOME, home, CAT, Dog, THRee")

[‘HOME’, ‘CAT’, ‘D’, ‘THR’]


[예제3] a로 시작하는 3글자짜리 문자열을 찾아라.

r = re.compile("^a..") 
r.findall("aDc, cba, acD, abC")

[‘aDc’]


[예제4] a가 2회이상 3회이하, b가 2회이상 3회이하인 문자열을 찾아라

r = re.compile("a{2,3}b{2,3}")
r.findall("aabb, aaabb, ab, aab, aaaaaaaaaaabbbbbbbbbbbbbbb")

[‘aabb’, ‘aaabb’, ‘aaabbb’]


search : compile에 지정된 정규표현식 패턴과 일치하는 문자열의 위치를 반환
group : 패턴과 일치하는 문자들을 그룹핑하여 추출


[예제5] 다음 주소에서 http:를 추출하여라.

p = re.compile(".+:")
m = p.search("http://google.com")
m.group()

‘http:’


  • sub(1st, 2nd) : 정규표현식과 일치하는 부분을 다른 문자로 바꿈.
  • 1st : ‘무엇으로(to)’ 바꿀것인가
  • 2nd : ‘무엇을(from)’ 바꿀것인가
    정규표현식과 일치하는 부분을 삭제하고 싶으면 1st"" 입력.

[예제6]

p = re.compile("(내|나의|내꺼)")
p.sub("그의", "나의 물건에 손대지 마시오.")

‘그의 물건에 손대지 마시오.’

3.2 사전처리


  • corpus(말뭉치) : 텍스트 마이닝에 적용되는 텍스트 데이터 집합
  • 정형화 : 원(raw)데이터를 정제하는 작업. 전처리와 동의어

3.2.1 대소문자 통일


파이썬은 대문자와 소문자를 서로 다른 문자로 인식하므로 둘중 하나로 통일해야한다.
대소문자 변환은 lower() 또는 upper() 매서드를 이용한다.


s = "Hello World"
print(s.lower(), s.upper())

hello world HELLO WORLD

3.2.1 숫자, 문장부호, 특수문자 제거


숫자, 문장부호, 특수문자는 단어가 아니므로 분석의 대상이 아닌 경우가 많다. 하지만 경우에 따라 삭제시 결과가 왜곡된다고 판단되면 남겨둘 수도 있다. 숫자는 정규 표현식을 이용해 제거한다.


p = re.compile("[0-9]+")
p.sub("","서울 부동산 가격이 올해 들어 평균 30% 상승했습니다.")

‘서울 부동산 가격이 올해 들어 평균 % 상승했습니다.’


문장부호, 특수문자 역시 정규표현식으로 삭제한다.

\W : 밑줄을 제외한 모든 특수문자, 문장부호를 가리키는 정규표현식

특수문자에는 공백(space)도 포함되므로 문장의 의미를 해치지 않기 위해서 삭제하는 것 보다 공백으로 바꾸는것이 더 좋다.


p = re.compile("\W+")
p.sub(" ","★서울 부동산 가격이 올해 들어 평균 30% 상승했습니다!")

’ 서울 부동산 가격이 올해 들어 평균 30 상승했습니다 ‘

p = re.compile("\W+")
s = p.sub(" ","주제_1: 건강한 몸과 건강한 정신!")
s

‘주제_1 건강한 몸과 건강한 정신 ‘


밑줄( _ )은 없애고싶다면 정제가 끝난 뒤 마지막에 한번 더 없앤다.


p = re.compile("_")
p.sub(" ",s)

‘주제 1 건강한 몸과 건강한 정신 ‘

3.2.3 불용어 제거


  • 불용어(stopwords) : 빈번하게 사용되나 구체적인 의미를 찾기 어려운 단어들 ex) a, the, an 등

언어마다 불용어 리스트를 라이브러리에서 제공해주는 경우가 많다. 분석가가 개인적으로 불용어 리스트를 만들어 추가할수도 있다.

  • NLTK : 파이썬에서 가장 많이 쓰는 텍스트마이닝 패키지. 언어별로 불용어리스트 제공하나 한국어는 지원하지 않음.

한국어 불용어 리스트는 아직까지 특정 패키지에서 지원하지 않으므로 개인적으로 작성하거나 다른 분석가들이 작성한 것을 활용해야함.


< 한국어에서 불용어 제거 >

words_Korean = ["추석","연휴","민족","대이동","시작","늘어","교통량"
,"교통사고","자동차","고장","상당수","차지","나타","것","기자"]
stopwords = ["가다","늘어","나타","것","기자"]
[i for i in words_Korean if i not in stopwords]

[‘추석’, ‘연휴’, ‘민족’, ‘대이동’, ‘시작’, ‘교통량’, ‘교통사고’, ‘자동차’, ‘고장’, ‘상당수’, ‘차지’]


< 영어에서 불용어 제거 >

from nltk.corpus import stopwords

words_English = ['chief', 'justice', 'roberts', ',', 'president', 'carter',
',', ',', 'president', 'clinton', ',', 'president', 'bush', 'president', 'obama',
',', 'fellow', 'americans', 'and', 'people', 'of', 'the', 'world', 'thank', 'you']
print([w for w in words_English if not w in stopwords.words('english')])

[‘chief’, ‘justice’, ‘roberts’, ‘,’, ‘president’, ‘carter’, ‘,’, ‘,’, ‘president’, ‘clinton’, ‘,’, ‘president’, ‘bush’, ‘president’, ‘obama’, ‘,’, ‘fellow’, ‘americans’, ‘people’, ‘world’, ‘thank’]

3.2.4 같은 어근 동일화(stemming)


NLTK 패키지에서 PorterStemmer 라이브러리를 통해 어근 통일화를 수행. 그 외에도 LancasterStemmer, RegexpStemmer도 있음.

한국어의 경우 stemming을 수행할 수 있는 라이브러리가 없어 형태소 분석기 이용.


from nltk.stem import PorterStemmer
from nltk.tokenize import word_tokenize

ps_stemmer = PorterStemmer()

new_text = "It is important to be immersed while you are pythoning with python. All pythoners have pythoned poorly at least once."

words = word_tokenize(new_text)

for w in words:
    print(ps_stemmer.stem(w), end=' ')

It is import to be immers while you are python with python . all python have python poorli at least onc .

from nltk.stem.lancaster import LancasterStemmer
LS_stemmer = LancasterStemmer()

for w in words:
    print(LS_stemmer.stem(w), end=' ')

it is import to be immers whil you ar python with python . al python hav python poor at least ont .

from nltk.stem.regexp import RegexpStemmer

RS_stemmer = RegexpStemmer("python")

for w in words:
    print(RS_stemmer.stem(w), end=' ')

It is important to be immersed while you are ing with . All ers have ed poorly at least once .

RegexpStemmer는 특정 표현식을 일괄 제거하는 역할을 한다. 위 코드에서는 python을 제거했다. RegexpStemmer는 Porter나 Lancaster가 처리하지 못하는 특수한 부분에서 쓰는 것이 좋다.


3.2.5 N-gram

  • n-gram : n번 연이어 등장하는 단어들의 연쇄.
  • 바이그램 : 두 번 연이어 등장
  • 트라이그램 : 세 번 연이어 등장

트라이그램 이상은 잘 활용하지 않는다. 엔그램은 보통 영어에만 적용한다.

바이그램 이상의 엔그램만 독자적으로 활용하는 것은 위험하다. 유니그램(1-gram)과 혼합하여 단어를 도출하는 것이 이상적이다.


from nltk import ngrams

sentence = "Chief Justice Roberts, President Cater, President Clinton, President Bush,President Obama, fellow Americans and people of the world, thank you.We, the citizens of America are now joined in a great national effort to rebuild our country and restore its promise for all of our people. Together, we will determine the course of America and the world for many, many years to come. We will face challenges. We will confront hardships, but we will get the job done."

grams = ngrams(sentence.split(), 2)

for gram in grams:
    print(gram, end=" ")

(‘Chief’, ‘Justice’) (‘Justice’, ‘Roberts,’) (‘Roberts,’, ‘President’) (‘President’, ‘Cater,’) (‘Cater,’, ‘President’) (‘President’, ‘Clinton,’) (‘Clinton,’, ‘President’) (‘President’, ‘Bush,’) (‘Bush,’, ‘President’) (‘President’, ‘Obama,’) (‘Obama,’, ‘fellow’) (‘fellow’, ‘Americans’) (‘Americans’, ‘and’) (‘and’, ‘people’) (‘people’, ‘of’) (‘of’, ‘the’) (‘the’, ‘world,’) (‘world,’, ‘thank’) (‘thank’, ‘you.’) (‘you.’, ‘We,’) (‘We,’, ‘the’) (‘the’, ‘citizens’) (‘citizens’, ‘of’) (‘of’, ‘America’) (‘America’, ‘are’) (‘are’, ‘now’) (‘now’, ‘joined’) (‘joined’, ‘in’) (‘in’, ‘a’) (‘a’, ‘great’) (‘great’, ‘national’) (‘national’, ‘effort’) (‘effort’, ‘to’) (‘to’, ‘rebuild’) (‘rebuild’, ‘our’) (‘our’, ‘country’) (‘country’, ‘and’) (‘and’, ‘restore’) (‘restore’, ‘its’) (‘its’, ‘promise’) (‘promise’, ‘for’) (‘for’, ‘all’) (‘all’, ‘of’) (‘of’, ‘our’) (‘our’, ‘people.’) (‘people.’, ‘Together,’) (‘Together,’, ‘we’) (‘we’, ‘will’) (‘will’, ‘determine’) (‘determine’, ‘the’) (‘the’, ‘course’) (‘course’, ‘of’) (‘of’, ‘America’) (‘America’, ‘and’) (‘and’, ‘the’) (‘the’, ‘world’) (‘world’, ‘for’) (‘for’, ‘many,’) (‘many,’, ‘many’) (‘many’, ‘years’) (‘years’, ‘to’) (‘to’, ‘come.’) (‘come.’, ‘We’) (‘We’, ‘will’) (‘will’, ‘face’) (‘face’, ‘challenges.’) (‘challenges.’, ‘We’) (‘We’, ‘will’) (‘will’, ‘confront’) (‘confront’, ‘hardships,’) (‘hardships,’, ‘but’) (‘but’, ‘we’) (‘we’, ‘will’) (‘will’, ‘get’) (‘get’, ‘the’) (‘the’, ‘job’) (‘job’, ‘done.’)

3.3 품사분석


품사분석 = POS(Part-Of-Speech)태깅

품사분석의 목적은 모든 언어에 공통적으로 존재하는 품사인 명사, 동사, 형용사, 부사를 살피는 것이다.

한국어 품사 분석은 KoNLPy 패키지 이용한다. 해당 패키지 내의 Kkma, Komoran, Hannanum, Twitter, Mecab 클래스를 연구자가 원하는 대로 선택하여 이용한다. 선택 기준은 실행 시간정확도이다.

  • Twitter는 클래스명이 konlpy v0.4.5부터 Okt로 바뀌었다.

클래스마다 정의하는 품사와 태깅 기호가 다르므로 사전에 숙지해야한다.

< 유용한 매서드 >
morphs : 문장을 형태소 단위로 끊는다.
nouns : 문장에서 명사만을 추출한다.
POS : 문장에 속한 각 형태소에 품사를 태깅한다.
Phrases : Twitter클래스의 매서드. 문장을 구 단위로 쪼갠다.


from konlpy.tag import Hannanum

hannanum = Hannanum()

print(hannanum.morphs("친척들이 모인 이번 추석 차례상에서는 단연 '집값'이 화제에 올랐다."))

[‘친척들’, ‘이’, ‘모이’, ‘ㄴ’, ‘이번’, ‘추석’, ‘차례상’, ‘에서는’, ‘단연’, “’”, ‘집값’, “’”, ‘이’, ‘화제’, ‘에’, ‘오르’, ‘아다’, ‘.’]

print(hannanum.nouns("친척들이 모인 이번 추석 차례상에서는 단연 '집값'이 화제에 올랐다."))

[‘친척들’, ‘이번’, ‘추석’, ‘차례상’, ‘집값’, ‘화제’]

print(hannanum.pos("친척들이 모인 이번 추석 차례상에서는 단연 '집값'이 화제에 올랐다.", ntags=9))

[(‘친척들’, ‘N’), (‘이’, ‘J’), (‘모이’, ‘P’), (‘ㄴ’, ‘E’), (‘이번’, ‘N’), (‘추석’, ‘N’), (‘차례상’, ‘N’), (‘에서는’, ‘J’), (‘단연’, ‘M’), (“’”, ‘S’), (‘집값’, ‘N’), (“’”, ‘S’), (‘이’, ‘J’), (‘화제’, ‘N’), (‘에’, ‘J’), (‘오르’, ‘P’), (‘아다’, ‘E’), (‘.’, ‘S’)]

print(hannanum.pos("친척들이 모인 이번 추석 차례상에서는 단연 '집값'이 화제에 올랐다.", ntags=22))

[(‘친척들’, ‘NC’), (‘이’, ‘JC’), (‘모이’, ‘PV’), (‘ㄴ’, ‘ET’), (‘이’, ‘NN’), (‘번’, ‘NB’), (‘추석’, ‘NC’), (‘차례상’, ‘NC’), (‘에서’, ‘JC’), (‘는’, ‘JX’), (‘단연’, ‘MA’), (“’”, ‘SR’), (‘집값’, ‘NC’), (“’”, ‘SR’), (‘이’, ‘JC’), (‘화제’, ‘NC’), (‘에’, ‘JC’), (‘오르’, ‘PV’), (‘아’, ‘EP’), (‘다’, ‘EF’), (‘.’, ‘SF’)]

from konlpy.tag import Kkma

kkma = Kkma()

print(kkma.morphs("친척들이 모인 이번 추석 차례상에서는 단연 '집값'이 화제에 올랐다."))

[‘친척’, ‘들’, ‘이’, ‘모이’, ‘ㄴ’, ‘이번’, ‘추석’, ‘차례’, ‘상’, ‘에서’, ‘는’, ‘단연’, “’”, ‘집’, ‘값’, “’”, ‘이’, ‘화제’, ‘에’, ‘오르’, ‘았’, ‘다’, ‘.’]

print(kkma.nouns("친척들이 모인 이번 추석 차례상에서는 단연 '집값'이 화제에 올랐다."))

[‘친척’, ‘이번’, ‘추석’, ‘차례’, ‘차례상’, ‘상’, ‘집’, ‘집값’, ‘값’, ‘화제’]

print(kkma.pos("친척들이 모인 이번 추석 차례상에서는 단연 '집값'이 화제에 올랐다."))

[(‘친척’, ‘NNG’), (‘들’, ‘XSN’), (‘이’, ‘JKS’), (‘모이’, ‘VV’), (‘ㄴ’, ‘ETD’), (‘이번’, ‘NNG’), (‘추석’, ‘NNG’), (‘차례’, ‘NNG’), (‘상’, ‘NNG’), (‘에서’, ‘JKM’), (‘는’, ‘JX’), (‘단연’, ‘MAG’), (“’”, ‘SS’), (‘집’, ‘NNG’), (‘값’, ‘NNG’), (“’”, ‘SS’), (‘이’, ‘MDT’), (‘화제’, ‘NNG’), (‘에’, ‘JKM’), (‘오르’, ‘VV’), (‘았’, ‘EPT’), (‘다’, ‘EFN’), (‘.’, ‘SF’)]

from konlpy.tag import Okt

okt = Okt()

print(okt.morphs("친척들이 모인 이번 추석 차례상에서는 단연 '집값'이 화제에 올랐다."))

[‘친척’, ‘들’, ‘이’, ‘모인’, ‘이번’, ‘추석’, ‘차례상’, ‘에서는’, ‘단연’, “’”, ‘집값’, “’”, ‘이’, ‘화제’, ‘에’, ‘올랐다’, ‘.’]

print(okt.nouns("친척들이 모인 이번 추석 차례상에서는 단연 '집값'이 화제에 올랐다."))

[‘친척’, ‘이번’, ‘추석’, ‘차례상’, ‘단연’, ‘집값’, ‘이’, ‘화제’]

print(okt.pos("친척들이 모인 이번 추석 차례상에서는 단연 '집값'이 화제에 올랐다."))

[(‘친척’, ‘Noun’), (‘들’, ‘Suffix’), (‘이’, ‘Josa’), (‘모인’, ‘Verb’), (‘이번’, ‘Noun’), (‘추석’, ‘Noun’), (‘차례상’, ‘Noun’), (‘에서는’, ‘Josa’), (‘단연’, ‘Noun’), (“’”, ‘Punctuation’), (‘집값’, ‘Noun’), (“’”, ‘Punctuation’), (‘이’, ‘Noun’), (‘화제’, ‘Noun’), (‘에’, ‘Josa’), (‘올랐다’, ‘Verb’), (‘.’, ‘Punctuation’)]

print(okt.phrases("친척들이 모인 이번 추석 차례상에서는 단연 '집값'이 화제에 올랐다."))

[‘친척들’, ‘이번’, ‘이번 추석’, ‘이번 추석 차례상’, ‘단연’, ‘집값’, ‘이 화제’, ‘추석’, ‘차례상’, ‘화제’]


영어 품사분석은 NLTK 패키지를 이용하여 수행할 수 있다.


from nltk import pos_tag

tokens = "The little yellow dog barked at the Persian cat.".split()
tags_en = pos_tag(tokens)
print(tags_en)

[(‘The’, ‘DT’), (‘little’, ‘JJ’), (‘yellow’, ‘JJ’), (‘dog’, ‘NN’), (‘barked’, ‘VBD’), (‘at’, ‘IN’), (‘the’, ‘DT’), (‘Persian’, ‘NNP’), (‘cat.’, ‘NN’)]

Leave a comment