BSA05-Data-Transform.ipynb
필요한 패키지
import pandas as pd
import numpy as np
from pandas.api.types import CategoricalDtype
import datetime
수치자료 → 범주형 자료
# 난수 값은 seed에 영향을 받음 (seed값을 지정해서 같은 결과가 나오도록)
np.random.seed(316)
정규난수 = np.random.normal(size=1000) # 정규분포를 따르는 난수 1000개를 발생시킴
정규난수[0:10] # 기본적으로 array 형태로 저장됨
# 구간 5개로 나눔 (구간의 길이가 동일하도록)
# (-3.118, -1.818], (-1.818, -0.525], (-0.525, 0.768], (0.768, 2.062], (2.062, 3.355]
동일구간 = pd.cut(정규난수,bins=5)
동일구간.describe() # 도수분포표 (구간 안에 몇 개의 데이터가 있는지)
# 정규분포를 따르는 난수를 발생했으므로 중간 구간에 해당하는 데이터가 많고, 양끝에는 적음
# (-3.5, -1.5] = A, (-1.5, -0.5] = B, ..., (1.5, 3.5] = E로 구간 설정
구간지정 = pd.cut(정규난수, bins=[-3.5, -1.5, -0.5, 0.5, 1.5, 3.5], labels=["A","B","C","D","E"])
구간지정.describe() # 빈도 확인
# 해당되는 객체의 개수가 동일하도록 구간 지정 (구간의 길이가 달라짐)
# 구간을 20%, 40%, 60%, 80%, 100% 비율로 구간 지정
동일개수 = pd.qcut(정규난수, q=5)
동일개수.describe()
# 25%씩 4개의 구간으로 나눔
비율지정 = pd.qcut(정규난수, q=[0, 0.25, 0.5, 0.75, 1.])
비율지정.describe()
# 명목자료로 표시할 때에는 labels를 설정해야 함
# ordered=False : 순서를 가지지 않는 nominal(명목형 자료)임
구간지정 = pd.cut(정규난수, bins=[-3.5, -1.5, -0.5, 0.5, 1.5, 3.5], labels=["A","B","C","D","E"], ordered=False)
# 범주값을 활용하고 싶은 경우
구간지정.categories
범주형 자료 → 수치자료
주택 = pd.read_csv("housing.csv")
주택.head()
# 내가 임의로 만든 문자열을 double quotation으로
# 파이썬에서 제공하는 것은 single quotation으로
주택["해변근접성"] = 주택['ocean_proximity'].astype('category')
주택["해변근접성"] # 크기 순서가 없는 명목형 자료임
# 명목형 자료는 가변수로
# 5개의 더미변수로 데이터프레임이 생성됨 (인덱스 자동 지정)
주택위치 = pd.get_dummies(주택["해변근접성"])
# 컬럼명은 가능한 공백이 없도록
주택위치.columns=["Ocean", "Inland", "Island", "NearBay", "NearOcean"]
순서자료 → 동일 간격의 수치 자료
# 명목자료를 순서자료로
순서지정 = ["A","B","C","D","E"] # A < B < C < D < E의 순서
순서구간 = 구간지정.astype(CategoricalDtype(categories=순서지정, ordered=True))
순서변환 = {"A":1, "B":2, "C":3, "D":4, "E":5} # mapping시키는 작업
순서구간 = 순서구간.map(순서변환).astype('uint8') # 순서자료(범주형) -> 숫자(수치자료)
# 그냥 변환하면 문자로 인식할 수도 있음
# uint8 : unsigned integer : 음수값 필요없으니까 (8bit의 integer)
# 순서자료가 아닌 일반 범주형 자료도 숫자(수치자료)로 변환 가능
변수의 type 확인
변수명 = 주택.columns.tolist() # 전체 변수명을 리스트의 형태로
print("전체변수명:", 변수명)
주택._get_numeric_data() # 문자형 데이터는 빠져있음
수치변수명 = 주택._get_numeric_data().columns.tolist()
범주변수명 = list(set(변수명)-set(수치변수명)) # 같은 것을 제외하고 다시 리스트로
print("수치변수명:", 수치변수명)
print("범주변수명:", 범주변수명)
주택.select_dtypes(exclude=np.number)
수치변수명 = 주택.select_dtypes(include=np.number).columns.tolist() # 숫자 데이터를 가져오기
범주변수명 = 주택.select_dtypes(exclude=np.number).columns.tolist() # 숫자 데이터를 버리기
print("수치변수명:", 수치변수명)
print("범주변수명:", 범주변수명)
표준화
주택.info()
수치자료 = 주택.iloc[:,[2,3,4,5,6,7]]
수치자료.head()
수치자료.mean() # axis=0 이 default값
# 표준화 (각 열의 평균을 계산해서 빼야 함)
수치자료-수치자료.mean(axis=0) # 열 기준으로 계산
표준자료 = (수치자료-수치자료.mean(axis=0))/수치자료.std(axis=0) # 표준편차로 나누기
표준자료.head()
정규화
# 정규화 (0~1 사이의 값으로 변환)
정규자료 = (수치자료-수치자료.min(axis=0))/(수치자료.max(axis=0)-수치자료.min(axis=0))
정규자료.tail()
시간자료 처리
# 시간 생성
pd.date_range("2023-3-2","2023-6-21") # 시작, 끝
# freq='D' : 주기를 하루 단위로 데이터 생성
pd.date_range("2023-3-2",periods=100) # 23/3/2일부터 하루 단위로 100일 간 날짜 생성
pd.date_range("2023-3-2", periods=5, freq='h') # 23/3/2 00:00:00부터 1시간 단위로 5개 시간 생성
# 문자열 데이터 -> 시간 자료
# date time index 사용
시간자료 = pd.DataFrame({'날짜':['2023-01-01 01:10:00', '2023-02-25 03:20:30',
'2023-03-02 06:30:00', '2023-04-19 10:40:30',
'2023-05-16 12:50:00', '2023-06-29 15:00:30',
'2023-07-01 18:10:00', '2023-08-15 21:50:30']})
시간자료.head() # '날짜'라는 하나의 변수에 8개의 데이터 입력
시간자료["날짜"] # 안에 있는 값만 사용하는 경우
# 시간자료로 변환
# errors='raise' : 에러 발생 시 예외 형태로 표시함
시간자료['날짜'] = pd.to_datetime(시간자료['날짜'], format='%Y-%m-%d %H:%M:%S', errors='raise')
시간자료.info()
시간자료 # 연,월,일,시,분,초를 각각 가져올 수 있음
시간자료['date'] = 시간자료['날짜'].dt.date # YYYY-MM-DD(문자)
시간자료['year'] = 시간자료['날짜'].dt.year # 연(4자리숫자)
시간자료['month'] = 시간자료['날짜'].dt.month # 월(숫자)
시간자료['월이름'] = 시간자료['날짜'].dt.month_name() # 월(문자)
시간자료['day'] = 시간자료['날짜'].dt.day # 일(숫자)
시간자료['time'] = 시간자료['날짜'].dt.time # HH:MM:SS(문자)
시간자료['hour'] = 시간자료['날짜'].dt.hour # 시(숫자)
시간자료['minute'] = 시간자료['날짜'].dt.minute # 분(숫자)
시간자료['second'] = 시간자료['날짜'].dt.second # 초(숫자자)
시간자료.head()
시간자료.info() # 숫자형(int)로 바뀌면서 연산이 가능해짐
날짜, 시간 조정
시간자료
시간자료['날짜']+datetime.timedelta(days=5) # 5일씩 더하는 작업
시간자료['날짜']+datetime.timedelta(days=-5) # 5일씩 빼는 작업
# 시간간격 조정 : resample
# np.random.randn(100) : 난수 100개 생성
# 난수를 series로 (dataframe의 한 줄(컬럼)처럼)
# 인덱스를 날짜로 (2023/1/1, 2023/1/2, ...)
시계열 = pd.Series(np.random.randn(100), index=pd.date_range("2023-1-1", periods=100, freq="D"))
시계열.head()
# 주 단위(week)로 데이터를 가져와서 7개의 평균을 계산하는 작업
시계열.resample('W').mean()
# freq="T" : 주기를 분 단위로
분당자료 = pd.Series(np.random.randn(100), index=pd.date_range("2023-1-1", periods=100, freq="T"))
분당자료.head()
# 10분간의 자료 중 open, high, low, close 값 출력
# 10분 단위로 잘라서 10개의 데이터의 o(시작점), h(제일 큰 값), l(제일 작은 값), c(마지막)
분당자료.resample('10T').ohlc()
'Statistics > BSA' 카테고리의 다른 글
230412 / BSA05. 데이터 전처리 2 : pyspark에서 결측값 처리 (0) | 2023.04.14 |
---|---|
230410 / BSA05. 데이터 전처리 2 : python에서 결측값 처리 (0) | 2023.04.14 |
230329 / BSA04. 오디오 데이터 처리하기 (0) | 2023.04.02 |
230329 / BSA04. 다양한 형식의 데이터 파일 읽고 저장하기 (0) | 2023.04.02 |
230327 / BSA04. 다양한 형태의 자료 파일 작업 속도 비교 (0) | 2023.04.02 |