본문 바로가기
Study/Data전처리 및 통계

Pandas(8)-한글 NLP

by 왕방개 2024. 2. 20.

**데이터 전처리

1.텍스트 데이터

1)한글 형태소 분석

 

=>형태소 분석기 설치 - kolnpy

-JDK(자바 개발 도구)를 설치

Java_Home 환경변수에 JDK 경로 설정

Path 에 JDK 의 bin 디렉토리 경로를 설정:Java 명령어를 콘솔에서 편리하게 사용하기 위해서

 

-Windows의 경우에는 Visual C++ 재배포 패키지 설치

visual studio 의 데스크 톱 애플리케이션 개발을 설치해도됨

 

-J-pype1 패키지 설치

pip install Jpype1

 

-konlpy설치: pip install konlpy

 

=>형태소 분석을 하는 이유

-우리나라는 공백 단위로 분할을 해서는 단어를 만들 수 없음.한국어는 조사가 뒤에 붙기 때문

공백 단위로 쪼개고 어간 추출을 하기 위해서 

-데이터 분석을 하다보면 특정 품사의 데이터만 필요한 경우가 발생

 

=>한글 형태소 분석기 모듈

-Hannanum

-Kkma

-Komoran

-Mecab

-Okt

-Twitter 가 있는데 최근에는 사용을 권장하지 않음

from konlpy.tag import Kkma
Kkma=Kkma()
#문장분석- 하나의 텍스트에 마침표가 있는 경우 분할
print(Kkma.sentences(text))
#단어별 분석- 명사만 추출
print(Kkma.nouns(text))
#형태소 분석 - 품사를 같이 제공: 이작업이 품사 태깅 - 자연어 처리의 한 분
print(Kkma.pos(text))
print("==============================================")
from konlpy.tag import Hannanum
hannanum=Hannanum()

#단어별 분석- 명사만 추출
print(hannanum.nouns(text))
#사용하는 단어 사전이 다르므로 앞의사전과 다른 결과
print(hannanum.pos(text))

from konlpy.tag import Okt
print("==============================================")
okt=Okt()
print(okt.pos(text))

 

2)BoW(Bag of Word)

 

=>텍스트 데이터에서 특정 단어의 등장 횟수를 나타내는 특성을 만드는 작업

=>워드 클라우드와 같이 등장 횟수를 이용해서 시각화를 위해서 수행하는 경우가 있고, 단어별 가중치를 적용하기 위해서 작업을 수행하기도 합니다.

어떤 문장을 분석할 때 단어별 가중치를 줄 수 있는데, 여기서 핵심은 한 문장에서 여러번 등장하면 중요하고, 여러문장에서 여러번 등장하면 그렇게 중요한 단어는 아님

=>scikit-learn의 CountVectorizer 클래스를 이용해서 인스턴스를 생성하고 fit_transform 함수에 문자열을 대입하면 BoW 특성 행렬을 만들어주고 to_array 함수를 호출하면 밀집 행렬로 결과를 리턴합니다.

=>instance 을 생성할 때 사용할 수 있는 옵션

-ngram_range:정수 형태의 튜플을 대입하면 ngram(단어가 연속으로 등장하는 경우 하나의 단어로 취급)옵션 설정 가능

-stop_words:불용어 설정

-vocabulary:횟수를 계산할 단어의 list

-max_df:최대 개수

-min_df:최소 개수

-max_feature:상위 몇개의 단어만 추출

=>인스턴스의 속성:get_feature_names()호출하면 각 특성에 연결된 단어를 확인

=>단어 별 빈도수 확인

import numpy as np
text_data= np.array(['사랑 사랑 사랑 잘가요 내 사랑 사랑 사랑','차오르는 나의 눈물이','온몸을 적셔도','127.0.0.1 Python'])

from sklearn.feature_extraction.text import CountVectorizer

#BoW객체 생성
countVectorizer=CountVectorizer(vocabulary=['사랑','python'])
bag_of_words=countVectorizer.fit_transform(text_data)
#희소행렬
print(bag_of_words)

#밀집 행렬
print(bag_of_words.toarray())

#각 열의 의미
print(countVectorizer.get_feature_names_out())

 

3)단어 별 가중치 적용

 

=>tf-idf(term frequency- inverse document frequency)를 이용한 가중치 계산

tf- 하나의 문서에 어떤 단어가 많이 등장할 수록 그 문서에서 다른 단어보다 중요한 단어

idf- 여러 문서에서 등장하는 단어가 있다면 이 단어는 중요하지 않을 가능성이 높음

- 가중치를 계산할때는 tf*idf

idf=log((1+문서의 개수)/(1+등장한문서빈도))+1

tf= 하나의 문서에서 등장한 빈도수

 

-scikit-learn 의 TfidfVectorizer 클래스를 제공

 

2.시계열 데이터

1)개요

=>날짜와 시간을 이용해서 정렬된 데이터로, 일정한 패턴을 가진 데이터도 시계열 데이터로 간주

물리적 흔적: 의학, 청각학 또는 기상학 등에서 측정한 물리적 흔적

 

2)pandas의 시계열 자료형

=>datetime64(TimeStamp):시계열 데이터를 저장하기 위한 자료형

tz 옵션을 이용해서 시간 대 설정이 가능

부등호를 이용해서 크기 비교 가능

뺄셈을 수행해서 간격을 알 수 있음

 

=>Period:두 시점 사이의 일정한 기간을 나타내는 자료형

데이터를 생성할 때 많이 이용

 

3)자료형 변환

=>문자열 데이터를 datetime64로 변환

-pandas의 to_datetime 함수 이용

날짜 형식의 문자열과 format 매개변수에 날짜 형식을 지정해서 생성하는데 format 을 생략하면 유추

errors 매개변수에 ignore을 설정하면 에러가 발생했을 때 문자열을 그대로 리턴하고 coerce을 설정하면 

문제가 발생하면 NaT를 설정하며 raise 을 설정하면 예외를 발생시켜서 중단

 

포맷은 %Y. %m(월), %d, %l(오전 오후 12시간제 시간), %p(AM PM),&H ,%M, %S 등이 존재합니다.

 

4)Period

=>to_peiod 함수를 이용해서 TimeStamp 객체를 일정한 기간을 나타내는 Period 객체로 변환이 가능

freq 옵션에 기준이 되는 기간을 설정

D(1일), W(1주),M(월말),MS(월초),Q(분기말),A(연말),AS(연초),B(휴일제외),H,T,S,L,U,N

 

import pandas as pd
df=pd.read_csv("stock-data.csv")
#df.info()


df['NewDate']=pd.to_datetime(df['Date'])
df.info()
#데이터를 출력하면 Date와 NewDate은 구분이 안되지만 자료형을 확인하면 다름
print(df.head())

#연속된 날짜는 인덱스로 많이 이용
df.set_index('NewDate',inplace=True)
print(df.head())

dates= ['2017-01-01','2018-06-03','2019-11-02']
pddates=pd.to_datetime(dates)
print(pddates)

#월로 변경 - 모든 날짜가 월 초나 월 말로 변경
pr_months=pddates.to_period(freq='M')
print(pr_months)

#분기로 변경
pr_months=pddates.to_period(freq='Q')
print(pr_months)

 

5)date_range

=>일정한 간격을 맞는 시계열 데이터를 생성해주는 함수

=>매개변수

start:시작 날짜

end:종료 날짜

periods:생성할 데이터 개수

freq:간격

tz:시간대 설정('Asia/Seoul')

ts_ms = pd.date_range(start='2024-01-01',end=None,periods=30,freq='D')

print(ts_ms)

 

6)날짜 데이터의 분리

=>pandas 의 Series 의 dt.단위를 이용

year, month, day, hour, minute, weekday(월요일이 0)을 이용

df['NewDate']=pd.to_datetime(df['Date'])

#연도만 추출
print(df['NewDate'].dt.year)

 

7)시차 특성을 갖는 데이터 생성

=>shift(간격, freq)을 이용하는데 이 함수는 pandas의 Series 의 함수


#날짜를 inedex로 갖는 Series 생성
ts= pd.Series(np.random.randn(20),index=df['NewDate'])
#이 경우 간격이 하루 단위가 아니라서 앞의 데이터가 밀려들어오는 것처럼 보이지 않ㅡㅇㅁ
#전부 하루 간격이라면 말려들어옵니다.
print(ts.shift(1))

 

8)결측치 처리

=>결측치 처리 방식은 삭제하거나 대체 하는 것

=>누락된 데이터의 기간을 삭제하는 바업

=>대체(inputation법); 관측에 기반에서 누락된 데이터를 채워넣는 방법

-누락된 데이터의 이전이나 이후값으로 채워넣는 방식

-이동 편균으로 데이터를 대체

-보간:인접한 데이터를 기반으로 누락된 데이터를 추정해서 대입하는 방법

DataFrame의 interpolate 함수를 이용

기본은 선형을 채우지만 method 에 quadratic 을 설정하면 비선형으로 채움

method 에 time설정하면 시간 기반

limit direction 을 이용해서 보간 방향을 설정

time_index= pd.date_range("01/01/2024",periods=5,freq='M')
dataframe= pd.DataFrame(index = time_index)
dataframe['Sales']=[1,2,np.nan,4,5]
print(dataframe.ffill())

print(dataframe.interpolate())

 

9) resampling

=>시계열의 빈도를 변환하는 것

=>다운 샘플링(데이터의 빈도를 줄이는 것)

-원본 데이터의 시간단위가 실용적이지 않은 경우:어떤 것을 너무 자주 측정하는 경우

게시판의 글을 분석하기 위해서 로그 데이터를 읽을 떄 시간 단위가 초까지 측정된 경우가 있다면 다운 샘플링을 고려

-계절 주기의 특정 부분에 집중해 하는 경우:하나의 특정 계절에만 초점을 맞춘 분석을 해야하는 경우

- 한 데이터를 낮은 빈도로 측정된 다른 데이터와 맞춰 주기 위해서

 

=>업 샘플링(데이터의 빈도를 늘리는 것 - 오버 샘플링)

-시계열이 불규칙적인 경우

-입력이 서로 다른 빈도로 샘플링된 상황에서 주기가 긴 데이터를 주기가 짧은 데이터에 맞추기 위해서

 

=>resample(freq,how,fill_method,closed,label,kind)

freq:주기를 설정하는 것으로 이전에 사용하던 방식도 가능하고 '문자열 단위',Hour,Minute, Second등을 이용해서 설정하는 것도 가능(Second(30))

 

how:채우는 값을 기본은 mean이고 first,last,max,min 설정 가능

 

fill_method:업 샘플링을 할 때 데이터를 채우는 방법으로 기본은 None이고 ffill이나 bfill 설정가능

 

limit: 채우는 개수

 

closed: 다운 샘플링을 할 때 왼쪽과 오른쪽 어떤 값을 사용할지 여부를 설정

 

label:어떤 인덱스를 사용할지 여부를 설정

range = pd.date_range('2024-02-01','2024-02-02',freq='2min')
df=pd.DataFrame(range[:20])
df['price']=np.random.randint(low=10,high=100,size=20)
df['amount']=np.random.randint(low=1,high=5,size=20)
#print(df)

#다운샘플링- 시간 간격을 10분으로 조정:4개의 데이터로 변경
downsampled_prices = df.set_index(0).price.resample('10T').first()
print(downsampled_prices)

#시계열 데이터의 경우 시간별 집계를 수행하는 방법
print(df.set_index(0).price.resample('10T').sum())

시계열을 기준으로 하는게 점점 중요해지는 이유가 클라우드 떄문.

퍼블릭 클라우드는 비용을 지불 해야하는데, 퍼블릭 클라우드의 최대장점은 스케일 업다운.

분석을 해서 늘렸다 줄였다 해야함. 당근이나 네이버 같은 경우는 트래픽이 엄청 많음.

시계열이라는 건 꼭 시간 데이터만이 아니라 index 1,2,3,4 도 시계열이라고 할 수 있음

 

10)이동시간 윈도우

=>일반적인 기술 통계는 전체 데이터를 기반으로 계산

=>이동시간 윈도우라는 것은 일정한 개수의 데이터를 가지고 움직이면서 기술통계를 계산

=>단순 이동 평균:현재 위치에서 일정한 개수를 설정하고 그 이전 데이터와의 평균 계산

DataFrame 의 rolling 함수를 이용해수 구하는데 window에 데이터 개수 설정

#2024 1월 1일부터 월 단위로 5개의 데이터 생성
time_index=pd.date_range("01/01/2024",periods=5,freq='M')

#위의 데이터를 인덱스로 해서 시계열 DataFrame을 생성
#pandas에서는 인덱스가 시간인 경우 또는 일정한 패턴인 경우를 시계열로 판
dataframe=pd.DataFrame(index=time_index)

dataframe['Stock_Price']=[1,2,3,4,5]

#단순 이동 평균 계산
print(dataframe.rolling(window=2).mean())

=>지수 이동 평균: 최근의 데이터에 가중치를 두는 방식

알파=1-span(기간)

[현재 데이터 + (1- 알파) 이전 데이터 + (1-알파)**2*이전에 이전 데이터] /[1+(1-알파)+(1-알파)**2]

DataFrame의 ewm 함수를 이용하고 span 옵션으로 span을 설정

#2024 1월 1일부터 월 단위로 5개의 데이터 생성
time_index=pd.date_range("01/01/2024",periods=5,freq='M')

#위의 데이터를 인덱스로 해서 시계열 DataFrame을 생성
#pandas에서는 인덱스가 시간인 경우 또는 일정한 패턴인 경우를 시계열로 판
dataframe=pd.DataFrame(index=time_index)

dataframe['Stock_Price']=[1,2,3,4,5]

#지수 이동 평균
print(dataframe.ewm(span=2).mean())

 

11)평활

=>시계열 자료의 체계적인 움직임을 찾아내기 위해서 과거 자료의 불규칙적인 변동을 제거하는 것

=>불규칙 변동의 제거를 이동 평균을 이용해서 분석

=>이동평균을 이용하는 것은 결국 과거 자료의 추세를 전 기간 또는 특정 기간 별로 평균을 계산해서 이를 통해서 미래자료를 예측한다는 것

=>과거 자료들의 가중치를 동일하게 적용하면 단순 이동 평균법이라고 하고 각 자료의 가중치를 다르게 적용하면 이를 지수 평활법이라고 합니다

 

12)계절성

=>데이터의 계절성은 특정 행동의 빈도가 안정적으로 반복해서 나타나는 것으로 동시에 여러 빈도가 다르게 발생하는 것

=>시계열 데이터 중에는 일일,주간,연간의 계절적인 변화를 갖는 경향이 있는 데이터가 있음

=>그래프를 이용해서 대략적인 계절성 요인을 확인

=>계절성 시계열

일련의 동작이 정해진 기간동안 반복되는 시계열 -주기가 일정

=>순환성 시계열

반복적인 동작이 있긴 하지만 기간이 일정하지 않음

주식 시작 이나 화산의 주기가 대표적인 순환성 시계열

=>계절성을 파악할 때는 산점도(Scatter) 보다는 선(plot) 그래프를 이용하는 것이 좋습니다

 

 

 

'Study > Data전처리 및 통계' 카테고리의 다른 글

기술 통계  (0) 2024.02.22
기초통계  (0) 2024.02.21
Pandas(7)-Outlier,Encoder,자연어처리  (0) 2024.02.19
Pandas(6)-Scaler 및 Normalization  (0) 2024.02.16
Pandas(5)  (0) 2024.02.15