프로그래밍 공부
KT AIVLE School 2주차 학습 - 데이터 처리 본문
2024-02-26(데이터 처리)
데이터 처리 과정
- 구조를 위한 전처리
- 모델링을 위한 전처리
데이터 프레임 변경
# rename() 메소드를 사용해 변경 전후의 열 이름을 딕셔너리 형태로 나열하는 방법으로 변경합니다.
# inplace=True 옵션을 설정해야 변경 사항이 실제 반영이 됩니다.
# rename() 함수로 열 이름 변경
data.rename(columns={'DistanceFromHome' : 'Distance',
'EmployeeNumber' : 'EmpNo',
'JobSatisfaction' : 'JobSat',
'MonthlyIncome' : 'M_Income',
'PercentSalaryHike' : 'PctSalHike',
'TotalWorkingYears' : 'TotWY'}, inplace=True)
# 확인
data.head()
# 모든 열 이름을 변경할 때는 columns 속성을 변경합니다.
# 변경이 필요없는 열은 기존 이름을 부여해 변경합니다.
# 모든 열 이름 변경
data.columns = ['Attr','Age','Dist','EmpNo','Gen','JobSat','Marital','M_Income', 'OT', 'PctSalHike', 'TotWY']
# 확인
data.head()
# 열추가는 없는 열을 변경하면 그 열이 추가
# final_amt 열 추가
data['Income_LY'] = data['M_Income'] / (1+data['PctSalHike']/100 )
data['Income_LY'] = round(data['Income_LY'])
# 확인
data.head()
# 데이터를 변경하기전에는 되돌리기 위한 준비가 필요
# data를 복사합니다. 깊은 복사
data2 = data.copy()
# drop() 메소드를 사용해 열을 삭제합니다.
# axis=0: 행 삭제(기본 값)
# axis=1: 열 삭제
# inplace=True 옵션을 지정해야 실제로 반영이 됩니다. <<<<<<<<<<<<<< 중요
# False : 삭제한 것 처럼 보여줘(조회!)
# 열 하나 삭제
data2.drop('Income_LY', axis=1, inplace=True)
# 확인
data2.head()
# 여러개를 삭제하려면 리스트 형태로
# 열 두 개 삭제
data2.drop(['JobSat2','Diff_Income'], axis=1, inplace=True)
# 확인
data2.head()
# 값 변경
# data를 복사합니다.
data2 = data.copy()
data2.head()
# 열 전체의 값 변경
# Income_LY의 값을 모두 0로 변경해 봅시다.
data2['Income_LY'] = 0
data2.head()
# 조건에 의한 값 변경
# Diff_Income 의 값이 1000보다 작은 경우, 0로 변경해 봅시다.
data2.loc[data2['Diff_Income'] < 1000, 'Diff_Income' ] = 0
data2.head()
# 조건에 의한 값 변경 2 np.where
# Age가 40보다 많으면 1, 아니면 0으로 바꿔 봅시다.
data2['Age'] = np.where(data2['Age'] > 40, 1, 0)
data2.head()
# 값 변경2 (map, cut)
# data를 복사합니다.
data2 = data.copy()
data2.head()
# map
# 주로 범주형 값을 다른 값으로 변경
# 다음 구문은 Gen 변수의 Male, Female을 각각 숫자 1, 0으로 변경
# Male -> 1, Female -> 0
data['Gen'] = data['Gen'].map({'Male': 1, 'Female': 0})
# 확인
data.head()
# pd.cut() 함수를 이용하여, 숫자형 변수를 범주형 변수로 변환할 수 있음
# 3 등분으로 분할
age_group = pd.cut(data2['Age'], 3)
age_group.value_counts()
# 3 등분으로 분할후 a,b,c로 이름 붙이기기
age_group = pd.cut(data2['Age'], 3, labels = ['a','b','c'])
age_group.value_counts()
# 내가 원하는 구간으로 자르기 bins = [ ]
# 나이를 다음 구간으로 분할합니다.
# 'young' : =< 40
# 'junior' : 40 < =< 50
# 'senior' : 50 <
age_group = pd.cut(data2['Age'], bins = [0, 40, 50, 100] , labels = ['young','junior','senior'])
age_group.value_counts()
# np의 무한대 np.inf
tmp = pd.cut(data2['PctSalHike'], bins = [-np.inf, 13, 18, np.inf], labels = ['L', 'M', 'H'])
tmp.value_counts()
데이터 프레임 결합
- concat
- pd.concat() - 매핑 기준 : 인덱스(행), 칼럼이름(열)
- 방향 - axis = 0 세로(행)로 합치기(위, 아래로 붙이기), 칼럼 이름 기준
- 방법 - join ‘outer’ : 모든 행과 열 합치기(기본 값), ‘inner’ : 같은 행과 열만 합침
- 방향 - axis = 1 가로(열)로 합치기(옆으로 붙여라), 행 인덱스 기준
- 방법 - join ‘outer’ : 모든 행과 열 합치기(기본 값) , ‘inner’ : 같은 행과 열만 합치기
- merge
- pd.merge() - 매핑 기준 : 특정 칼럼(key) 값 기준
- pivot
concat
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sales = pd.read_csv("sales.csv")
sales1 = sales.loc[sales['Store_ID']==1]
sales2 = sales.loc[sales['Store_ID']==2]
sales5 = sales.loc[sales['Store_ID']==5]
sales11 = sales.loc[sales['Store_ID']==11]
products = pd.read_csv("product.csv")
stores = pd.read_csv("store.csv")
df1 = pd.DataFrame({'A':[10,25], 'B':[15,30]})
df2 = pd.DataFrame({'A':[20,30, 50], 'C':[35,30, 40]})
df2.drop([1], inplace = True)
display(df1)
display(df2)
pd.concat([df1, df2], axis = 0, join = 'inner')
pd.concat([df1, df2], axis = 0, join = 'outer')
pd.concat([df1, df2], axis = 1, join = 'inner')
pd.concat([df1, df2], axis = 1, join = 'outer')
merge
df1 = pd.DataFrame({'A':[1,2], 'B':[15,30], 'C':[20, 25]})
df2 = pd.DataFrame({'A':[2,3], 'D':[20, 35]})
display(df1)
display(df2)
# 기본 형태
# pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, suffixes=('_x', '_y'), sort=False, validate=None)
# 예
pd.merge(df1, df2, how = 'inner', on = 'A')
left right머지 사용 예
한쪽은 값이 있고 한쪽은 값이 없을 때
주로 outer는 잘 안쓰임
시계열 데이터 처리
시계열 데이터란
- 행과 행에 시간의 순서가 있고
- 행과 행의 시간 간격이 동일한 데이터
- 순차 데이터임
날짜 요소 뽑기
- 날짜 타입의 변수로 부터 날짜의 요소를 뽑아 낼 수 있음
- .dt.날짜요소
- .dt.isocalendar().week << weekofyear에서 변경
시간에 따른 흐름 추출 - Time Lag
- .shift()
- 시계열 데이터에서 시간의 흐름 전후로 정보를 이동시킬 때 사용
- 데이터가 한 칸씩 밀림
- ex) shift(), shift(2), shift(-1)
시간에 따른 흐름 추출 - Moving Average
- rolling().mean()
- 시간의 흐름에 따라 일정 기간 동안 평균을 이동하면서 구함
시간에 따른 흐름 추출 - 차분
- 특정 시점 데이터, 이전 시점 데이터와의 차이 구하기
- .diff()
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sales = pd.read_csv("sales_simple.csv")
products = pd.read_csv("product_master.csv")
# 판매액 계산하기
temp = pd.merge(sales, products)
temp['Amt' ] = temp['Qty'] * temp['Price']
temp['Amt'] = (temp['Amt']/1000).round() # 단위 1000달러
# 집계
data1 = temp.groupby(['Date', 'Category'], as_index = False)['Amt'].sum()
data2 = temp.groupby(['Date'], as_index = False)['Amt'].sum()
# 피봇
data11 = data1.pivot(index = 'Date', columns = 'Category', values = 'Amt').reset_index()
# 합치기
data = pd.merge(data2, data11)
data.head()
data.info()
data['Date'] = pd.to_datetime(data['Date'])
data.info()
# pd.to_datetime(date, format = '%d/%m/%Y') # format = '%d/%m/%Y' 입력되는 날짜가 이런 형태야~~ 라고 알려주는 옵션
date = pd.Series(['03-01-2023', '03-02-2023', '03-03-2023'])
date = pd.to_datetime(date)
date
# 만약 dd-mm-yyyy 이 맞다면!
date = pd.Series(['03-01-2023', '03-02-2023', '03-03-2023'])
date = pd.to_datetime(date, format = '%d-%m-%Y') #입력받은 날짜 데이터 형식이 '%d-%m-%Y'!
date
# 시간에 따른 흐름
# shift
temp = data.loc[:,['Date','Amt']]
# 전날 매출액 열을 추가합시다.
temp['Amt_lag'] = temp['Amt'].shift() #default = 1
# 전전날 매출액 열을 추가.
temp['Amt_lag2'] = temp['Amt'].shift(2) # 2행 shift
# 다음날 매출액 열을 추가합시다.
temp['Amt_lag_1'] = temp['Amt'].shift(-1)
temp.head()
# 7일 이동평균 매출액을 구해 봅시다.
temp['Amt_MA7_1'] = temp['Amt'].rolling(7).mean()
temp['Amt_MA7_2'] = temp['Amt'].rolling(7, min_periods = 1).mean()
temp.head(10)
# 차분을 구해 봅시다.
temp['Amt_D1'] = temp['Amt'].diff()
temp['Amt_D2'] = temp['Amt'].diff(2)
temp.head(10)
# 연습문제
# data의 Grocery가 매출이 가장 높습니다. 이에 대해서 다음의 열을 추가해 봅시다.
# 전날 매출액
# 7일 전(전주 동 요일) 매출액
# 3일 이동평균 매출액
# 전날대비 매출액 증감여부 (증가 1, 감소 -1, 동일 0)
# 전날 매출액
data['Eve'] = data['Grocery'].shift()
# 7일 전(전주 동 요일) 매출액
data['7-ago'] = data['Grocery'].shift(7)
# 3일 이동평균 매출액
data['3d_avg'] = data['Grocery'].rolling(3, min_periods = 1).mean()
# 전날대비 매출액 증감여부 (증가 1, 감소 -1, 동일 0)
data['Eve_PM'] = data['Grocery'].diff().map(lambda x: 1 if x > 0 else (-1 if x < 0 else 0))
temp['Gro_Diff'] = temp['Grocery'].diff()
temp['Gro_Diff1'] = np.where(temp['Gro_Diff'] > 0, 1, np.where(temp['Gro_Diff'] == 0, 0, -1))
temp['Gro_Diff2'] = pd.cut(temp['Gro_Diff'], bins =[-np.inf, -0.5, 0.5, np.inf], labels = [-1,0,1])
# bins = [-np.inf ,-1, 0, np.inf ] temp.head(10)
data.head(20)
요약 : 시계열 데이터 다루기
- 시계열 데이터
- 행과 행 사이에 시간의 흐름, 동일한 시간 간격이 있는 데이터
- 날짜 요소 뽑기
- 날짜 타입으로 변환 후 .dt.날짜요소로 추출가능
CRISP-DM
무엇이 문제?
- 비지니스 문제정의
- 데이터 분석 방향, 목표결정
- 초기 가설 수립
- ex) 환율 → 내일 주가 등등
- 정보 → 원본식별(어디에 있나)
- 하나의 데이터프레임
- 데이터분석 EDA&CDA
- 모델링을 위한 데이터 구조 만들기
- 모델을 만들고 검증하기
- 기술적 관점 평가, 비지니스적 관점 평가
- 비지니스 문제 이해 - 가설 수립
- 수립절차
- 해결해야 할 문제 파악
- Y를 해결하기 위한 요인(x) 찾기
- 가설의 구조를 정의 (X → Y)
- 수립절차
- 데이터 이해
- 데이터 원본 식별 및 취득
- 있는 데이터
- 그대로 사용가능
- 가공해야 사용가능
- 없는 데이터
- 취득 가능
- 취득 불가능
- 있는 데이터
- 데이터 탐색 : EDA, CDA
- EDA 탐색적 분석
- CDA 확증적 분석
- 도구 - 통계(수치)화 도구, 시각화 도구
- 다음 사항이 필요 : 그래프, 통계량, 가설검정 방법(도구) + 해석
- 다음 순서대로 진행
- 단변량 분석 - 개별 변수의 분포
- 이변량 분석1 : feature와 target간의 관계 (가설을 확인하는 단계)
- 이변량 분석2 : feature들 간의 관계
- 데이터 원본 식별 및 취득
- 데이터 준비
- 모델링
- 데이터로부터 패턴을 찾는 과정
- 오차를 최소하는 패턴
데이터의 시각화
- Focus
- 시각화의 목적은 비지니스의 인사이트를 파악
- 한계
- 요약된 정보가 표현
- 관점에 다라 해석이 다를 수 이음
- 요약을 하면 정보의 손실이 발생
2024-02-27(데이터 처리2)
시각화 라이브러리
- matplotlib.pyplot
- 별칭으로 plt 사용
- Seaborn의 별칭은 sns
- 기본
- plt.plot() - 기본 라인차트를 그려줌
- plt.show() - 그래프를 화면에 출력해줌
Code
import pandas as pd
import numpy as np
# 시각화 라이브러리
import matplotlib.pyplot as plt
import seaborn as sns
path = 'airquality.csv'
data = pd.read_csv(path)
data['Date'] = pd.to_datetime(data['Date'])
data.dropna(axis = 0, inplace = True)
data.head()
# 차트 그리기
plt.plot(data['Temp'])
# 화면에 보여주기
plt.show()
# x축 y축 지정
# 타입1
plt.plot(data['Date'], data['Temp'])
plt.show()
# 타입2
plt.plot('Date', 'Temp', data = data)
plt.show()
# x축 y축 꾸미기
plt.plot(data['Date'], data['Ozone'])
plt.xticks(rotation = 30) # x축 값 꾸미기 : 방향을 30도 틀어서
plt.xlabel('Date') # x축 이름 지정
plt.ylabel('Ozone') # y축 이름 지정
plt.title('Daily Airquality') # 타이틀
plt.show()
# 꾸미기 +
plt.plot(data['Date'], data['Ozone']
,color='green' # 칼러
, linestyle='dotted' # 라인스타일
, marker='o') # 값 마커(모양)
plt.xlabel('Date')
plt.ylabel('Ozone')
plt.title('Daily Airquality')
plt.xticks(rotation=45)
plt.show()
# 여러 그래프 한번
# 첫번째 그래프
plt.plot(data['Date'], data['Ozone'], color='green', linestyle='dotted', marker='o')
# 두번째 그래프
plt.plot(data['Date'], data['Temp'], color='r', linestyle='-', marker='s')
plt.xlabel('Date')
plt.ylabel('Ozone')
plt.title('Daily Airquality')
plt.xticks(rotation=45)
# 위 그래프와 설정 한꺼번에 보여주기
plt.show()
# 범례 그리드 추가
plt.plot(data['Date'], data['Ozone'], label = 'Ozone') # label = : 범례추가를 위한 레이블값
plt.plot(data['Date'], data['Temp'], label = 'Temp')
plt.legend(loc = 'upper right') # 레이블 표시하기. loc = : 위치
plt.grid()
plt.show()
# 연습문제
plt.figure(figsize = (12, 8))
plt.plot('Date', 'Ozone', data = data, label = 'Ozone', marker = 'o')
plt.plot('Date', 'Temp', data = data, label = 'Temp', marker = 'o')
plt.plot('Date', 'Wind', data = data, label = 'Wind', marker = 'o')
plt.xlabel('Date')
plt.title('Airquality')
plt.legend(loc = 'upper right')
plt.grid()
plt.show()
단변량 분석 - 숫자형
숫자형 변수 정리법
- 숫자로 요약 : 평균, 중앙, 최빈, 사분위수등
- 평균 - 산술, 조화, 기하
- 평균을 대푯값으로 사용할 때 주의해야 함
- 정규분포일 때나 유의미함
- 사분위수 - 오름차순 정렬 후 전체를 4등분하고 경계에 해당하는 값(25%,50%,75%)
- 2사분위수(50%) - 중위수, 중앙값
- 중위수(자료의 순서상 가운데 위치)
- 최빈값
- 평균 - 산술, 조화, 기하
- 구간을 나누고 빈도(frequency)수 계산 - 도수분포표
기초 통계량 - 숫자 몇 개로 분포를 요약
# 시리즈 기초 통계량
titanic['Fare'].describe()
# 데이터프레임의 숫자타입 변수들 기초통계량 조회
titanic.describe()
숫자형 변수 시각화 히스토그램
- 주의점 bins를 적절히 조절
- 구간의 개수에 따라서 파악할 수 있는 내용이 달라짐
- 단점 - 구간(bin)의 너비에 따라 모양이 달라짐
밀도함수 그래프 Density Plot(KDE Plot)
sns.kdeplot(titanic['Fare'])
# sns.kdeplot(x='Fare', data = titanic)
plt.show()
Box Plot
박스 & 수염
- 쉽게 설명하자면 직사각형 부분이 box 이고 거기서 뻗어 나온 직선 같은것이 수염
- 박스 : 4분위 수
- 박스의 시작 부분은 Q1 - 25%
- 박스의 중간 부분은 Q2 - 50%
- 박스의 끝 부분은 Q3 - 75%
- IQR
- 3사분위수(Q3) - 1사분위(Q1)
# titanic['Age']에는 NaN이 있습니다. 이를 제외한 데이터
temp = titanic.loc[titanic['Age'].notnull()]
# 세
plt.boxplot(temp['Age'])
plt.grid()
plt.show()
# 가로
plt.boxplot(temp['Age'], vert = False)
plt.grid()
plt.show()
# sns는 NaN을 자동으로 빼
sns.boxplot(x = titanic['Age'])
plt.grid()
plt.show()
단변량 분석 - 범주형
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
path = 'titanic_simple.csv'
titanic = pd.read_csv(path)
titanic.head()
path = 'air.csv'
air = pd.read_csv(path)
air.head()
# 범주별 빈도수
titanic['Embarked'].value_counts()
#범주별 비율
titanic['Embarked'].value_counts(normalize = True)
# bar chart
sns.countplot(x = 'Pclass', data = titanic)
plt.grid()
plt.show()
# 연습문제
sns.countplot(x = 'Embarked', data = titanic)
#plt.bar(titanic['Survived'].value_counts().index, titanic['Survived'].value_counts().values)
plt.grid()
plt.show()
정리
기준, | 입력, | 방향 | |
---|---|---|---|
concat / | df의 구조 / | [ ] / | axis=0, 1 |
merge / | 특정열의 값 / | _, _ / | x, 옆으로 병합 |
CRISP-DM
- 비지니스 이해
- 문제 정의
- 분석 방향 목표
- 가설 x → y (x, y는 정보 - 범주형, 수치형)
- 데이터 이해
- 원본(소스) 식별
- 하나의 Data Frame만들기
- 분석
- 1단계 - 개별정보 분석(단변량)
| | 수치형 | 범주형 |
| --- | --- | --- |
| 기초통계량 | min,max, 사분위수 등 | 범주별 빈도수, 비율 |
| 그래프 | 히스토그램, kde, plot | bar plot |
2. 2단계 - x → y가 맞는지 판단
3. 3단계 - x1, x2의 관계 분석
후기
대학 재학중일때 파이썬과 데이터에 친숙하지 못해서 강의에 소홀했었는데 이렇게 다시 학습해보니
나도 노력하면 할 수 있다는 것을 느끼게 되어서 만족감을 느끼고 뿌듯했다
'KT AIVLE School' 카테고리의 다른 글
KT AIVLE School 미니프로젝트 6-1, 2일차(데이터 전처리) (0) | 2024.04.29 |
---|---|
KT AIVLE School 미니프로젝트 6-1, 1일차(데이터분석) (0) | 2024.04.29 |
KT AIVLE School 3주차 학습 - 웹 크롤링 (2) | 2024.03.16 |
KT AIVLE School 2주차 학습 - 데이터 분석 (5) | 2024.03.16 |
KT AIVLE School 1주차 학습 - Numpy, Pandas (1) | 2024.03.16 |
Comments