Post

[KT Aivle 3기 AI] 5일차. (1) DataFrame 변경

0. 개요

KT Aivle School 3기 AI 5일차

  • 주제 : DataFrame 변경
  • 강사 : 한기영 강사님
  • 내용 : 4일차에 이어 Pandas의 DataFrame을 다루는 방법에 대해서 알려주셨다. 그 중, DataFrame 변경하는 부분에 대한 정리이다.

1. 데이터 전처리 과정

데이터 전처리에는 두가지 단계가 있다

  1. 데이터 구조 만들기
  2. 모델링을 위한 전처리

data_preprocessing

그 중 데이터 구조 만들기 부분을 공부해보자.

1) 데이터 구조 만들기

데이터 구조 만들기에는

  • DataFrame 변경
    • 칼럼 추가, 삭제
    • 숫자를 범주로 변환하기
  • DataFrame 합치기
    • concat, merge
    • pivot
  • 시계열 데이터 다루기
    • rolling, shift
  • 데이터분석 방법론
    • 문제정의, 가설수립
    • EDA&CDA 개요
  • 시각화 라이브러리 : Matplotlib
  • 개별 변수 분석 도구 (단변량 분석)

이 있고, 이 중 DataFrame 변경 부분에 대해 정리해보려 한다.

2. DataFrame 변경

1) 열 이름 변경

  • 기존 데이터프레임의 열 이름을 적절히 변경해야 할 경우가 있다.
  • 또는 집계 결과를 가진 열 이름을 이해하기 쉽게 변경해야 할 경우도 있다.

(1) 일부 열 이름 변경

  • rename() 메소드를 사용해 변경 전후의 열 이름을 딕셔너리 형태로 나열하는 방법으로 변경한다.
  • inplace=True 옵션을 설정해야 변경 사항이 실제 반영이 된다.
1
2
3
4
5
6
7
8
9
import pandas as pd
import numpy as np

# 데이터 읽어오기
path = 'https://raw.githubusercontent.com/DA4BAM/dataset/master/Attrition_simple2.CSV'
data = pd.read_csv(path)  

# 상위 3개 확인
data.head(3)
AttritionAgeDistanceFromHomeEmployeeNumberGenderJobSatisfactionMaritalStatusMonthlyIncomeOverTimePercentSalaryHikeTotalWorkingYears
00337817Male3Married11691No1114
1035181412Male4Single9362No1110
204261911Male1Married13348No1318
1
2
3
4
5
6
7
8
9
10
# rename() 함수로 열 이름 변경
data.rename(columns={'DistanceFromHome' : 'Distance', 
                    'EmployeeNumber' : 'EmpNo',
                    'JobSatisfaction' : 'JobSat',
                    'MonthlyIncome' : 'M_Income',
                    'PercentSalaryHike' : 'PctSalHike',
                    'TotalWorkingYears' : 'TotWY'}, inplace=True)

# 확인
data.head()
AttritionAgeDistanceEmpNoGenderJobSatMaritalStatusM_IncomeOverTimePctSalHikeTotWY
00337817Male3Married11691No1114
1035181412Male4Single9362No1110
204261911Male1Married13348No1318
304621204Female1Married17048No2328
41224593Male3Single3894No164

(2) 모든 열 이름 변경

  • 모든 열 이름을 변경할 때는 columns 속성을 변경한다.
  • 변경이 필요없는 열은 기존 이름을 부여해 변경한다.
1
2
3
4
5
# 모든 열 이름 변경
data.columns = ['Attr','Age','Dist','EmpNo','Gen','JobSat','Marital','M_Income', 'OT', 'PctSalHike', 'TotWY']

# 확인
data.head()
AttrAgeDistEmpNoGenJobSatMaritalM_IncomeOTPctSalHikeTotWY
00337817Male3Married11691No1114
1035181412Male4Single9362No1110
204261911Male1Married13348No1318
304621204Female1Married17048No2328
41224593Male3Single3894No164

2) 열 추가

  • 새로운 열을 추가하여 기존 데이터에서 계산된 결과값을 저장해야할 경우가 있다.
  • 작년 급여액을 계산해서 열을 추가해 보자.
    • 올해 급여 : MonthlyIncome(M_Income)
    • 급여 인상율 : PercentSalaryHike(PctSalHike)
    • 작년 급여 * ( 1 + PctSalHike / 100 ) = M_Income
    • 작년 급여 = M_Income / (( 1 + PctSalHike / 100 )
1
2
3
4
5
# final_amt 열 추가
data['Income_LY'] = data['M_Income'] / (1+data['PctSalHike']/100 )
data['Income_LY'] = round(data['Income_LY'])
# 확인
data.head()
AttrAgeDistEmpNoGenJobSatMaritalM_IncomeOTPctSalHikeTotWYIncome_LY
00337817Male3Married11691No111410532.0
1035181412Male4Single9362No11108434.0
204261911Male1Married13348No131811812.0
304621204Female1Married17048No232813860.0
41224593Male3Single3894No1643357.0
  • (참고) insert() 메소드를 사용하면 원하는 위치에 열을 추가할 수 있으나.. DataFrame의 칼럼의 위치를 너무 신경쓰지 말자.

3) 열 삭제

  • 뭔가를 삭제할 때는 항상 조심x100 해야 한다.
  • 잘못 되었을 때 되돌리기 위한 준비가 필요하다.
  • 원본 데이터를 copy하고 작업을 하도록 하자.
1
2
# data를 복사합니다.
data2 = data.copy()

(1) 열 하나 삭제

  • drop() 메소드를 사용해 열을 삭제한다.
  • axis = 0 : 행 삭제 (default)
  • axis = 1 : 열 삭제
  • inplace = True 옵션을 지정해야 실제로 반영이 된다!
    • False : 삭제한 것 처럼 보여줘 (조회)
1
2
3
4
5
# 열 하나 삭제
data2.drop('Income_LY', axis=1, inplace=True)

# 확인
data2.head()
AttrAgeDistEmpNoGenJobSatMaritalM_IncomeOTPctSalHikeTotWY
00337817Male3Married11691No1114
1035181412Male4Single9362No1110
204261911Male1Married13348No1318
304621204Female1Married17048No2328
41224593Male3Single3894No164

(2) 여러 열 삭제

  • 삭제할 열을 리스트 형태로 전달에 한 번에 여러 열을 제거할 수 있다.
1
2
3
4
5
# 열 두 개 삭제
data2.drop(['Marital','Gen'], axis=1, inplace=True)

# 확인
data2.head()
AttrAgeDistEmpNoJobSatM_IncomeOTPctSalHikeTotWY
00337817311691No1114
103518141249362No1110
204261911113348No1318
304621204117048No2328
4122459333894No164

4) 값 변경 1

  • 뭔가를 변경할 때도 항상 조심x100 해야 한다.
  • 잘못 되었을 때 되돌리기 위한 준비가 필요하다.
  • 원본 데이터를 copy하고 작업을 하도록 하자.
1
2
3
# data를 복사합니다.
data2 = data.copy()
data2.head(3)
AttrAgeDistEmpNoGenJobSatMaritalM_IncomeOTPctSalHikeTotWYIncome_LY
00337817Male3Married11691No111410532.0
1035181412Male4Single9362No11108434.0
204261911Male1Married13348No131811812.0

(1) 열 전체 값 변경

1
2
3
# Income_LY의 값을 모두 0로 변경해 봅시다.
data2['Income_LY'] = 0
data2.head()
AttrAgeDistEmpNoGenJobSatMaritalM_IncomeOTPctSalHikeTotWYIncome_LY
00337817Male3Married11691No11140
1035181412Male4Single9362No11100
204261911Male1Married13348No13180
304621204Female1Married17048No23280
41224593Male3Single3894No1640

(2) 조건에 의한 값 변경 1

1
2
3
# M_Income 의 값이 1000보다 작은 경우, 0로 변경해 봅시다.
data2.loc[data2['M_Income'] < 4000, 'M_Income' ] = 0
data2.head()
AttrAgeDistEmpNoGenJobSatMaritalM_IncomeOTPctSalHikeTotWYIncome_LY
00337817Male3Married11691No11140
1035181412Male4Single9362No11100
204261911Male1Married13348No13180
304621204Female1Married17048No23280
41224593Male3Single0No1640

(3) 조건에 의한 값 변경 2

  • 이번에는, np.where()를 이용해보자.
1
2
3
# Age가 40보다 많으면 1, 아니면 0으로 바꿔 봅시다.
data2['Age'] = np.where(data2['Age'] > 40, 1, 0)
data2.head()
AttrAgeDistEmpNoGenJobSatMaritalM_IncomeOTPctSalHikeTotWYIncome_LY
0007817Male3Married11691No11140
100181412Male4Single9362No11100
20161911Male1Married13348No13180
30121204Female1Married17048No23280
4104593Male3Single0No1640

5) 값 변경 2 (map, cut)

(1) map()

  • 주로 범주형 값을 다른 값으로 변경
  • 다음 구문은 Gen 변수의 Male, Female을 각각 숫자 1, 0으로 변경한다.
1
2
3
4
5
6
7
8
# data를 복사합니다.
data2 = data.copy()

# Male -> 1, Female -> 0
data2['Gen'] = data2['Gen'].map({'Male': 1, 'Female': 0})

# 확인
data2.head()
AttrAgeDistEmpNoGenJobSatMaritalM_IncomeOTPctSalHikeTotWYIncome_LY
0033781713Married11691No111410532.0
103518141214Single9362No11108434.0
20426191111Married13348No131811812.0
30462120401Married17048No232813860.0
4122459313Single3894No1643357.0

(2) cut()

  • pd.cut() 함수를 이용하여, 숫자형 변수를 범주형 변수로 변환할 수 있다.
  • 다음 구문은 나이를 나이대로 변경하는 구문이다.
1
data2['Age'].describe()
1
2
3
4
5
6
7
8
9
count    1196.00000
mean       36.94398
std         9.09270
min        18.00000
25%        30.00000
50%        36.00000
75%        43.00000
max        60.00000
Name: Age, dtype: float64
  • 전체 범위 균등 분할하기
    • 값의 범위를 균등 분할하는 것이지, 값이 개수를 균등하게 맞추는 것은 아님!
1
2
3
# 3 등분으로 분할
age_group = pd.cut(data2['Age'], 3)
age_group.value_counts()
1
2
3
4
(32.0, 46.0]      590
(17.958, 32.0]    413
(46.0, 60.0]      193
Name: Age, dtype: int64
1
2
3
#  3 등분으로 분할후 a,b,c로 이름 붙이기기
age_group = pd.cut(data2['Age'], 3, labels = ['a','b','c'])
age_group.value_counts()
1
2
3
4
b    590
a    413
c    193
Name: Age, dtype: int64
  • 내가 원하는 구간으로 자르기 : bins = []
1
2
3
4
5
6
7
# 나이를 다음 구간으로 분할합니다.
# '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()
1
2
3
4
young     820
junior    262
senior    114
Name: Age, dtype: int64

값의 범위 중 오른쪽(큰값)이 아닌 왼쪽(작은값)이 포함되도록 하려면 pd.cut 함수 옵션에 right = False 라고 지정해야 합니다.
https://pandas.pydata.org/docs/reference/api/pandas.cut.html

1
2
age_group = pd.cut(data2['Age'], bins =[0, 40, 50, 100], right=False)
age_group.value_counts()
1
2
3
4
[0, 40)      775
[40, 50)     282
[50, 100)    139
Name: Age, dtype: int64

[예제] data2의 PctSalHike 열에 대해서 다음의 범주로 분할하시오.

  • ‘L’ : =< 13
  • ‘M’ : 13 < =< 18
  • ‘H’ : 18 <
1
pd.cut(data2['PctSalHike'], bins=[-np.inf, 13, 18, np.inf], labels=['L', 'M', 'H'])
1
2
3
4
5
6
7
8
9
10
11
12
13
0       L
1       L
2       L
3       H
4       M
       ..
1191    L
1192    L
1193    M
1194    M
1195    H
Name: PctSalHike, Length: 1196, dtype: category
Categories (3, object): ['L' < 'M' < 'H']
This post is licensed under CC BY 4.0 by the author.

[KT Aivle 3기 AI] 4일차. (3) Pandas

[KT Aivle 3기 AI] 5일차. (2) DataFrame 결합