본문 바로가기

배운 책들 정리/파이썬 머신러닝 판다스 데이터분석

파이썬 머신러닝 판다스 데이터 분석 5,6 - 데이터 사전 처리, 데이터프레임의 다양한 응용

5장 데이터 사전 처리

1. 범주형 데이터 처리

 

* 범주형 데이터 처리

 

# %%
# 범주형(카테고리) 데이터 처리
# 데이터 구간 분할

import pandas as pd
import numpy as np
df=pd.read_csv(r'/content/drive/MyDrive/BDA/part4/auto-mpg.csv', header=None)

df.columns = ["mpg","cylinders","displacement","horsepower",
            "weight","acceleration","model year","origin","name"]

# horsepower 열의 누락 데이터("?")를 삭제하고 실수형으로 변환
df["horsepower"].replace("?",np.nan, inplace=True)
df.dropna(subset=["horsepower"], axis=0,inplace=True)
df["horsepower"]=df["horsepower"].astype("float")
df["horsepower"].dtypes


# %%
# 구간 정의
count, bin_dividers = np.histogram(df["horsepower"],bins=3)
print(bin_dividers)

# 3개의 bin에 이름 지정
bin_names = ["저출력","보통출력","고출력"]

# pd.cut 함수로 각 데이터를 3개의 bin에 할당
df["hp_bin"] = pd.cut(x=df["horsepower"],
                      bins=bin_dividers,
                      labels=bin_names,
                      include_lowest=True)

# horsepower 열, hp_bin 열의 첫 15행 출력
print(df[["horsepower","hp_bin"]].head(15))

 

 

* 더미 변수

 

# %%
# 더미 변수 (0과 1을 가지는 변수)
# 그룹의 -1개를 넣어줘야 함 (나머지는 0으로 취급 되니)

# np.histogram 함수로 3개의 bin으로 구분할 경계값의 르스트 구하기
count, bin_dividers = np.histogram(df["horsepower"],bins=3)

# pd.cut으로 각 데이터를 3개의 bin에 할당
bin_names = ["저출력","보통출력","고출력"]
df["hp_bin"] = pd.cut(x=df["horsepower"],
                      bins=bin_dividers,
                      labels=bin_names,
                      include_lowest=True)

# hp_bin 열의 범주형 데이터를 더미 변수로 변환
horsepower_dummies = pd.get_dummies(df["hp_bin"])
print(horsepower_dummies.head(15))

 

* 원핫인코딩

 

# %%
# 원핫인코딩

from sklearn import preprocessing

# 전처리
label_encoder = preprocessing.LabelEncoder()
onehot_encoder = preprocessing.OneHotEncoder()

# 문자열 범주 -> 숫자형 범주
onehot_labeled = label_encoder.fit_transform(df["hp_bin"].head(15))
print(onehot_labeled)
print(type(onehot_labeled))

# 1차원 -> 2차원 행렬 변경
onehot_reshaped = onehot_labeled.reshape(len(onehot_labeled),1)   
print(onehot_reshaped)
print(type(onehot_reshaped))

# 희소행렬로 변환
onehot_fitted = onehot_encoder.fit_transform(onehot_reshaped)  
print(onehot_fitted)
print(type(onehot_fitted))

 

* 출력값 확인

 

print(df["hp_bin"][10:15], onehot_labeled[10:15], onehot_fitted[10:15])
# 데이터프레임 df의 "hp_bin" 열에서 10번부터 15번까지의 값을 출력하고, 
# 해당 구간에 대한 one-hot 인코딩된 레이블과 실제 학습된 one-hot 인코딩 값을 출력하는 코드입니다.

 

 

2. 정규화

 

* 정규화

 

# %%
# 정규화
import pandas as pd
import numpy as np

# read_csv() 함수로 df 생성
df = pd.read_csv(r"/content/drive/MyDrive/BDA/part4/auto-mpg.csv")

df.columns = ["mpg","cylinders","displacement","horsepower",
            "weight","acceleration","model year","origin","name"]


# horsepower 열의 누락 데이터 삭제하고 실수형 변환
df["horsepower"].replace("?",np.nan, inplace=True)
df.dropna(subset=["horsepower"], axis=0,inplace=True)
df["horsepower"]=df["horsepower"].astype("float")

# horsepower 열의 통계 요약 정보로 최대값(max) 확인
print(df.horsepower.describe())
print("\n")

# horsepower 열의 최대값의 절대값으로 모든 데이터를 나눠서 저장
df.horsepower = df.horsepower/abs(df.horsepower.max())

print(df.horsepower.head())
print("\n")
print(df.horsepower.describe())

 

* 최대값의 절대값으로 모든 데이터 나눠서 저장

 

 

# %%
# 데이터 저장 (최대값, 최소값)
# 최소값&최대값 이용하는 방법
# 0과 1의 범위를 일정하게 맞추어주는 정규화 값 : (관측치 - 최소값) / (최대값 - 최소값)
# 관측치가 최소값 => 0
# 관측치가 최대값 => 1
# 계산된 값의 범위는 0 ~ 1

# horsepower 열의 통계 요약 정보로 최대값(max)과 최소값(min) 확인
print(df.horsepower.describe())
print("\n")

# horsepower 열의 최대값의 절대값으로 모든 데이터를 나눠서 저장
min_x = df.horsepower - df.horsepower.min()
min_max = df.horsepower.max() - df.horsepower.min()
df.horsepower - min_x/min_max

print(df.horsepower.head())
print("\n")
print(df.horsepower.describe())

 

 

 

3) 시계열 데이터

 

* 시계열 객체로 변환

 

# 타임스탬프 TImestamp = 날짜별
# 피리어드 Period = 날짜의 기간
# %%
# 시계열 데이터
# 문자열 Timestamp로 변환
import pandas as pd

# read_csv() 함수로 CSV 파일을 가져와서 df로 변환
df = pd.read_csv("/content/drive/MyDrive/BDA/part5/stock-data.csv")

# 데이터 내용 및 자료형 확인
print(df.head())
print("\n")
print(df.info())


# %%
# 문자열 데이터를 판다스 Timestamp로 변환 (현재 날짜 자료형은 문자열)
df["new_Date"] = pd.to_datetime(df["Date"])

# 데이터 내용 및 자료형 확인
print(df.head())
print("\n")
print(df.info())
print(type(df["new_Date"][0]))
# datetime64[ns] => Timestamp 의 자료형

 

 

* 시계열 값으로 변환된 열을 새로운 행 인덱스로 지정, 기존 날짜 열은 삭제

 

# %%
# 시계열 값으로 변환된 열을 새로운 행 인덱스로 지정, 기존 날짜 열은 삭제
df.set_index("new_Date",inplace=True)
df.drop("Date",axis=1,inplace=True)

# 데이터 내용 및 자료형 확인
print(df.head())
print("\n")
print(df.info())

 

 

* Timestamp를 Perio로 변환

 

# %%
# Timestamp를 Period로 변환
dates = ["2019-01-01","2020-03-01","2021-06-01"]

# 문자열의 배열(시리즈 객체)을 판다스 Timestamp로 변환
ts_dates = pd.to_datetime(dates)
print(ts_dates)
print("\n")

# Timestamp를 Period로 변환
pr_day = ts_dates.to_period(freq="D") # 연
print(pr_day)
pr_month = ts_dates.to_period(freq="M") # 월
print(pr_month)
pr_year = ts_dates.to_period(freq="A") # 일
print(pr_year)

 

* 시계열 데이터 만들기

 

# %%
# 시계열 데이터 만들기
# 배열 만들기 - 월 간격, 월의 시작일 기준
ts_ms = pd.date_range(start="2019-01-01",
                      end=None,
                      periods=6,
                      freq="MS", # 월의 시작 일 & 월 간격
                      tz="Asia/Seoul")
print(ts_ms)
print("\n")

# 월 간격, 월의 마지막 날 기준
ts_me = pd.date_range(start="2019-01-01",
                      periods=6,
                      freq="M", # 월의 마지막 일 & 월 간격
                      tz="Asia/Seoul")
print(ts_me)
print("\n")

# 분기 (3개월) 간격, 월의 마지막 날 기준
ts_3m = pd.date_range("2019-01-01",periods=6,
                      freq="3M",
                      tz="Asia/Seoul")
print(ts_3m)

 

* Period 배열 만들기

 

# %%
# Period 배열 만들기
# 1개월 길이
pr_m = pd.date_range(start="2019-01-01",
                      end=None,
                      periods=3,
                      freq="M")
print(pr_m)

# 1개월 길이
pr_h = pd.date_range(start="2019-01-01",
                      end=None,
                      periods=3,
                      freq="H")
print(pr_h)

# 1개월 길이
pr_2h = pd.date_range(start="2019-01-01",
                      end=None,
                      periods=3,
                      freq="2H")
print(pr_2h)

 

 

* 다른 간격으로 표현

 

# %%
# Period 배열
sd_prd = pd.period_range(start="2019-01-01",
                      end=None,
                      periods=6,
                      freq="M", # 월 간격
                      )
print(sd_prd)

sd_prd1 = pd.period_range(start="2019-01-01",
                      end=None,
                      periods=6,
                      freq="H", # 1시간 간격
                      )
print(sd_prd1)

sd_prd2 = pd.period_range(start="2019-01-01",
                      end=None,
                      periods=6,
                      freq="2H", # 1시간 간격
                      )
print(sd_prd2)

 

 

4) 날짜 인덱싱

 

# %%
# 시계열 데이터 활용
# 날짜 데이터 분리
df = pd.read_csv("/content/drive/MyDrive/BDA/part5/stock-data.csv")

# 문자열 -> Timestamp 변환 
df["new_Date"] = pd.to_datetime(df["Date"])
print(df.head())
print("\n")

# dt 속성을 이용하여 new_Date 열의 연-월-일 정보를 년, 월, 일로 구분
df["Year"] = df["new_Date"].dt.year
df["Month"] = df["new_Date"].dt.month
df["Day"] = df["new_Date"].dt.day
print(df.head())
print("\n")

 

* 날짜 데이터 분리

 

# %%
# 날짜 데이터 분리
# Timestamp를 Period로 변환하여 연-월-일 표기 변경하기
df["Date_yr"] = df["new_Date"].dt.to_period(freq="A")
df["Date_m"] = df["new_Date"].dt.to_period(freq="M")
print(df.head())
print("\n")

df.set_index("Date_m",inplace=True)
print(df.head())

 

 

* 날짜 인덱스 활용

 

# %%
# 날짜 인덱스 활용
# 날짜 데이터 분리
df = pd.read_csv("/content/drive/MyDrive/BDA/part5/stock-data.csv")

# 문자열 -> Timestamp 변환 
df["new_Date"] = pd.to_datetime(df["Date"])
df.set_index("new_Date",inplace=True)

print(df.head())
print("\n")
print(df.index)

 

 

* 날짜 인덱스 이용해서 데이터 선택하기 

 

# %%
# 날짜 인덱스 이용해서 데이터 선택하기
df_y = df["2018"]
print(df_y.head())
print('\n')
df_ym = df.loc["2018-07"]
print(df_ym)
print('\n') # loc 인덱서 활용

df_ym_cols = df.loc["2018-07","Start":"High"] # 열 범위 슬라이싱
print(df_ym_cols)
print('\n')

df_ymd = df.loc[["2018-07-02"]]
print(df_ymd)
print("\n")

df_ymd_range = df["2018-06-20":"2018-06-25"] # 날짜 범위 지정
print(df_ymd_range)

.

 

* 시간 간격 계산, 최근 180일~189일 사이의 값들만 선택하기

 

# %%
# 시간 간격 계산, 최근 180일~189일 사이의 값들만 선택하기
today = pd.to_datetime("2018-12-25")
df["time_delta"] = today - df.index
df.set_index("time_delta", inplace=True)
df_180 = df["180 days":"189 days"]
print(df_180)

 

6장 데이터프레임 응용

1. 함수 매핑

 

* 개별 원소에 적용

 

# %%
import seaborn as sns

# titanic 데이터셋에서 age, fare 2개 열을 선택하여 데이터프레임 만들기
titanic = sns.load_dataset("titanic")
df = titanic.loc[:,["age","fare"]]
df["ten"] = 5
print(df.head())

# %%
# 시리즈의 원소에 apply() 적용
def add_5 (n) :
    return n + 10
def add_two_obj(a,b):
    return a+b

print(add_5(5))
print(add_two_obj(5,5))

 

 

* 시리즈의 원소에 apply() 적용 // applymap() 적용

 

# %%
# 시리즈의 원소에 apply() 적용
# 시리즈 객체에 적용
sr1 = df["age"].apply(add_5)
print(sr1.head())
# 시리즈 객체와 숫자에 적용 : 2개의 인수 (시리즈 +숫자)
sr2 = df["age"].apply(add_two_obj, b=5)
print(sr2.head())   
# lambda 함수 활용 : 시리즈 객체에 적용
sr3 = df["age"].apply(lambda x: add_5(x))
print(sr3.head())   

# %%
# 데이터프레임 원소에 applymap() 적용
# titanic 데이터 셋에서 age, fare 2개 열을 선택하여 데이터 프레임 만들기
titanic = sns.load_dataset("titanic")
df = titanic.loc[:,["age","fare"]]
print(df.head())

def add_5 (n) :
    return n + 5

df_map = df.applymap(add_5)
print(df_map.head())

 

 

* 데이터 프레임 원소 (lambda 표현)

 

# %%
# 데이터 프레임 원소 (lambda 표현)
df.applymap(add_5)
df.applymap(lambda x : x+5)
df.applymap(lambda x : add_5(x))

 

 

2) 시리즈 객체에 적용

 

* 시리즈 객체에 함수 매핑

 

# %%
# 시리즈 객체에 함수 매핑
# 데이터프레임에 apply(axis=0) 적용
# 1) 반환하는 값이 여러 개인 경우
# 널값에 대한 불 인덱스 반환하는 함수
def missing_value(series): # 시리즈를 인자로 전달
    return series.isnull() # 불린 시리즈를 반환

# 데이터 프레임에 apply 메소드를 적용
result = df.apply(missing_value, axis=0)
print(result.head())
print("\n")
print(type(result))

 

* 반환하는 값이 한 개인 경우

 

# %%
# 2) 반환하는 값이 한 개인 경우
# 범위를 구하는 함수:
def range_xy(series):
    return series.max()- series.min()
df.apply(missing_value, axis=0)

 

 

* 데이터프레임에 apply(axis=0) 적용 // 데이터프레임의 각 행에 함수 매핑

 

# %%
# 데이터프레임에 apply(axis=0) 적용
# 사용자 함수 정의
def min_max(x):
    return x.max() - x.min()

result = df.apply(min_max)
print(result)
print("\n")
print(type(result))

# %%
# 데이터프레임의 각 행에 함수 매핑
# 데이터프레임에 apply() 적용
df["ten"]=10
print(df.head())
print("\n")

# 사용자 함수 정의
def add_two_obj(a,b):
    return a+b

# 데이터프레임의 2개 열에 적용
# x=df, a=df["age"], b=df["ten"]
df["add"] = df.apply(lambda x: add_two_obj(x["age"], x["ten"]), axis=1)
print(df.head())

 

 

3) 데이터 프레임 객체 함수 매핑

 

* 데이터 프레임 객체 함수 매핑 // 데이터프레임 함수 매핑

 

# %%
# 데이터프레임의 객체에 함수 매핑
# 데이터프레임에 pipe() 적용

# 각 열의 NaN 찾기 - 데이터프레임을 전달하면 데이터프레임 반환
def missing_value(x): # 시리즈를 인자로 전달
    return x.isnull()  

# 각 열의 NaN 개수 반환 - 데이터프레임을 전달하면 시리즈 반환
def missing_count(x):
    return missing_value(x).sum() 

# 데이터프레임의 총 NaN 개수 반환 - 데이터프레임을 전달하면 값 반환
def total_number_missing(x):
    return missing_count(x).sum()   


# %%
# 데이터프레임에 함수 매핑
result_df = df.pipe(missing_value)
print(result_df.head())
print(type(result_df)) # 데이터프레임 = 함수 적용 결과가 여러 개 (시리즈 개수와 동일)

# 누락 데이터 개수 시리즈 형태로 반환 - 함수 적용 결과가 하나
result_series = df.pipe(missing_count)
print(result_series)
print(type(result_series))

# 각 열의 누락 데이터 개수 합산해서 반환 - 함수 적용 결과가 개별값
result_value = df.pipe(total_number_missing)
print(result_value)
print(type(result_value))

 

 

4) 열 재구성

 

* 열 순서 바꾸기 // 열 리스트 만들기 ~ 재배치하기

 

# %%
# 열 재구성
# 열 순서 바꾸기 (필요한 열 선택)
df = titanic.loc[0:4, "survived":"age"]
print(df, "\n")

# %%
# 열 이름의 리스트 만들기
columns = list(df.columns.values) # 기존 열 이름
print(columns,"\n")

# 열 이름을 알파벳 순으로 정렬하기
columns_sorted = sorted(columns)
df_sorfed = df[columns_sorted]
print(df_sorfed, "\n")

# 열 이름을 기존 순서의 정반대 역순으로 정렬하기
columns_reversed = list(reversed(columns))
df_reversed = df[columns_reversed]
print(df_reversed, "\n")

# 열 이름을 사용자가 정의한 임의의 순서로 재배치하기
columns_customed = ["pclass","sex","age","survived"]
df_customed = df[columns_customed]
print(df_customed, "\n")

 

 

5) 열 분리하기

 

* 연,월,일 데이터 분리 후 새로운 열 추가하기

 

# %%
# 열 분리
import pandas as pd

df = pd.read_excel(r"/content/drive/MyDrive/BDA/part6/주가데이터.xlsx", engine="openpyxl")
print(df.head())
print(df.dtypes)

# 연,월,일 데이터 분리하기
df["연월일"] = df["연월일"].astype("str")
dates = df["연월일"].str.split("-")
print(dates.head())

# 분리된 정보를 각각 새로운 열에 담아 df에 추가하기
df["연"] = dates.str.get(0)
df["월"] = dates.str.get(1)
df["일"] = dates.str.get(2)
print(df.head())

 

6) 필터링 - 불린 인덱싱

 

* 조건 걸어서 필터링 결과만 출력하기

 

# %%
# 필터링
# 불린 인덱싱
# 나이가 10대(10~19세)인 승객만 따로 선택
import seaborn as sns
titanic = sns.load_dataset("titanic")
mask1 = (titanic.age>=10)&(titanic.age<20)
df_teenage = titanic.loc[mask1, :]
print(df_teenage.head())

# 나이가 10세 미만(0~9세)이고 여성인 승객만 따로 선택
mask2 = (titanic.age<10)&(titanic.sex=="female")
df_female_under10 = titanic.loc[mask2, :]
print(df_female_under10.head())

# 나이가 10세 미만(0~9세) 또는 60세 이상인 승객의 age, sex, alone 열만 선택
mask3 = (titanic.age<10) | (titanic.age >= 60)
df_under10_morethan60 = titanic.loc[mask3, ["age","sex","alone"]]
print(df_under10_morethan60.head())

 

 

* isin() 메소드

 

# %%
# isin 메소드 활용
# Ipyhton 디스플레이 설정 변경 - 출력할 최대 열의 개수
pd.set_option("display.max_columns",10)

# 함께 탑승한 형제 또는 배우자의 수가 3,4,5인 승객만 따로 추출 - 불린 인덱싱
mask3 = titanic["sibsp"] == 3
mask4 = titanic["sibsp"] == 4
mask5 = titanic["sibsp"] == 5
df_boolean = titanic[mask3 | mask4 | mask5]
print(df_boolean.head())

# isin() 메소드 활용하여 동일한 조건으로 추출
isin_filter = titanic["sibsp"].isin([3,4,5])
df_isin = titanic[isin_filter]
print(df_isin.head())

 

 

7) 데이터 프레임 합치기

 

* 데이터 프레임 연결 (concatenate)

 

 

 

* 데이터프레임 연결 (concat)

 

# %%
# 데이터프레임 연결(concat)

# ignore_index=True 옵션 설정하기
result2 = pd.concat([df1,df2],ignore_index=True)
print(result2)

# 2개의 데이터프레임을 좌우 열 방향으로 이어 붙이듯 연결하기
result3 = pd.concat([df1,df2], axis=1)
print(result3)

 

 

* join=inner 옵션 적용 후 (교집합) 여러 방향으로 연결해보기

 

# %%
# 데이터프레임 연결(concat)
# join="inner" 옵션 적용하기(교집합)
result3_in = pd.concat([df1,df2],axis=1,join="inner")
print(result3_in)

sr1 = pd.Series(["e0","e1","e2","e3"], name="e")
sr2 = pd.Series(["f0","f1","f2"], name="f", index=[3,4,5])
sr3 = pd.Series(["g0","g1","g2","g3"], name="g")

# df1과 sr1을 좌우 열 방향으로 연결하기
result4 = pd.concat([df1,sr1], axis=1)
print(result4)

# df2과 sr2을 좌우 열 방향으로 연결하기

result5 = pd.concat([df2,sr2], axis=1, sort=True)
print(result5)

# sr1과 sr3을 좌우 열 방향으로 연결하기
# axis = 1 => 좌우
result6 = pd.concat([sr1,sr3],axis=1)
print(result6)
# axis = 0 => 위아래
result7 = pd.concat([sr1,sr3],axis=0)
print(result6)

 

 

* 핵심

- join=inner 사용법 익숙해지기

- 범주형 데이터 처리 , 정규화,  함수 맵핑, 합치기, 연결하기 익숙해지기

 

 

* 오늘 작성한 코드 (0428 Python)

 

guromd1

 

guromd1.blogspot.com

 

 

* 링크 (작성한 계정으로 로그인)

 

Google Colaboratory Notebook

Run, share, and edit Python notebooks

colab.research.google.com

 

 

 

728x90
반응형
LIST