[Pandas 기초] 5. DataFrame 변경
Python Library 중 하나인 Pandas에서 DataFrame을 변경하는 방법을 알아보자.
열 이름 변경
- 기존 데이터프레임의 열 이름을 적절히 변경해야 할 경우가 있다.
- 또는 집계 결과를 가진 열 이름을 이해하기 쉽게 변경해야 할 경우도 있다.
일부 열 이름 변경
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)
Attrition | Age | DistanceFromHome | EmployeeNumber | Gender | JobSatisfaction | MaritalStatus | MonthlyIncome | OverTime | PercentSalaryHike | TotalWorkingYears | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 33 | 7 | 817 | Male | 3 | Married | 11691 | No | 11 | 14 |
1 | 0 | 35 | 18 | 1412 | Male | 4 | Single | 9362 | No | 11 | 10 |
2 | 0 | 42 | 6 | 1911 | Male | 1 | Married | 13348 | No | 13 | 18 |
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()
Attrition | Age | Distance | EmpNo | Gender | JobSat | MaritalStatus | M_Income | OverTime | PctSalHike | TotWY | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 33 | 7 | 817 | Male | 3 | Married | 11691 | No | 11 | 14 |
1 | 0 | 35 | 18 | 1412 | Male | 4 | Single | 9362 | No | 11 | 10 |
2 | 0 | 42 | 6 | 1911 | Male | 1 | Married | 13348 | No | 13 | 18 |
3 | 0 | 46 | 2 | 1204 | Female | 1 | Married | 17048 | No | 23 | 28 |
4 | 1 | 22 | 4 | 593 | Male | 3 | Single | 3894 | No | 16 | 4 |
모든 열 이름 변경
- 모든 열 이름을 변경할 때는 columns 속성을 변경한다.
- 변경이 필요없는 열은 기존 이름을 부여해 변경한다.
1
2
3
4
5
# 모든 열 이름 변경
data.columns = ['Attr','Age','Dist','EmpNo','Gen','JobSat','Marital','M_Income', 'OT', 'PctSalHike', 'TotWY']
# 확인
data.head()
Attr | Age | Dist | EmpNo | Gen | JobSat | Marital | M_Income | OT | PctSalHike | TotWY | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 33 | 7 | 817 | Male | 3 | Married | 11691 | No | 11 | 14 |
1 | 0 | 35 | 18 | 1412 | Male | 4 | Single | 9362 | No | 11 | 10 |
2 | 0 | 42 | 6 | 1911 | Male | 1 | Married | 13348 | No | 13 | 18 |
3 | 0 | 46 | 2 | 1204 | Female | 1 | Married | 17048 | No | 23 | 28 |
4 | 1 | 22 | 4 | 593 | Male | 3 | Single | 3894 | No | 16 | 4 |
열 추가
- 새로운 열을 추가하여 기존 데이터에서 계산된 결과값을 저장해야할 경우가 있다.
- 작년 급여액을 계산해서 열을 추가해 보자.
- 올해 급여 : 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()
Attr | Age | Dist | EmpNo | Gen | JobSat | Marital | M_Income | OT | PctSalHike | TotWY | Income_LY | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 33 | 7 | 817 | Male | 3 | Married | 11691 | No | 11 | 14 | 10532.0 |
1 | 0 | 35 | 18 | 1412 | Male | 4 | Single | 9362 | No | 11 | 10 | 8434.0 |
2 | 0 | 42 | 6 | 1911 | Male | 1 | Married | 13348 | No | 13 | 18 | 11812.0 |
3 | 0 | 46 | 2 | 1204 | Female | 1 | Married | 17048 | No | 23 | 28 | 13860.0 |
4 | 1 | 22 | 4 | 593 | Male | 3 | Single | 3894 | No | 16 | 4 | 3357.0 |
- (참고)
insert()
메소드를 사용하면 원하는 위치에 열을 추가할 수 있으나.. DataFrame의 칼럼의 위치를 너무 신경쓰지 말자.
열 삭제
- 뭔가를 삭제할 때는 항상 조심x100 해야 한다.
- 잘못 되었을 때 되돌리기 위한 준비가 필요하다.
- 원본 데이터를 copy하고 작업을 하도록 하자.
1
2
# data를 복사합니다.
data2 = data.copy()
열 하나 삭제
drop()
메소드를 사용해 열을 삭제한다.- axis = 0 : 행 삭제 (default)
- axis = 1 : 열 삭제
inplace = True
옵션을 지정해야 실제로 반영이 된다!- False : 삭제한 것 처럼 보여줘 (조회)
1
2
3
4
5
# 열 하나 삭제
data2.drop('Income_LY', axis=1, inplace=True)
# 확인
data2.head()
Attr | Age | Dist | EmpNo | Gen | JobSat | Marital | M_Income | OT | PctSalHike | TotWY | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 33 | 7 | 817 | Male | 3 | Married | 11691 | No | 11 | 14 |
1 | 0 | 35 | 18 | 1412 | Male | 4 | Single | 9362 | No | 11 | 10 |
2 | 0 | 42 | 6 | 1911 | Male | 1 | Married | 13348 | No | 13 | 18 |
3 | 0 | 46 | 2 | 1204 | Female | 1 | Married | 17048 | No | 23 | 28 |
4 | 1 | 22 | 4 | 593 | Male | 3 | Single | 3894 | No | 16 | 4 |
여러 열 삭제
- 삭제할 열을 리스트 형태로 전달에 한 번에 여러 열을 제거할 수 있다.
1
2
3
4
5
# 열 두 개 삭제
data2.drop(['Marital','Gen'], axis=1, inplace=True)
# 확인
data2.head()
Attr | Age | Dist | EmpNo | JobSat | M_Income | OT | PctSalHike | TotWY | |
---|---|---|---|---|---|---|---|---|---|
0 | 0 | 33 | 7 | 817 | 3 | 11691 | No | 11 | 14 |
1 | 0 | 35 | 18 | 1412 | 4 | 9362 | No | 11 | 10 |
2 | 0 | 42 | 6 | 1911 | 1 | 13348 | No | 13 | 18 |
3 | 0 | 46 | 2 | 1204 | 1 | 17048 | No | 23 | 28 |
4 | 1 | 22 | 4 | 593 | 3 | 3894 | No | 16 | 4 |
값 변경 1
- 뭔가를 변경할 때도 항상 조심x100 해야 한다.
- 잘못 되었을 때 되돌리기 위한 준비가 필요하다.
- 원본 데이터를 copy하고 작업을 하도록 하자.
1
2
3
# data를 복사합니다.
data2 = data.copy()
data2.head(3)
Attr | Age | Dist | EmpNo | Gen | JobSat | Marital | M_Income | OT | PctSalHike | TotWY | Income_LY | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 33 | 7 | 817 | Male | 3 | Married | 11691 | No | 11 | 14 | 10532.0 |
1 | 0 | 35 | 18 | 1412 | Male | 4 | Single | 9362 | No | 11 | 10 | 8434.0 |
2 | 0 | 42 | 6 | 1911 | Male | 1 | Married | 13348 | No | 13 | 18 | 11812.0 |
열 전체 값 변경
1
2
3
# Income_LY의 값을 모두 0로 변경해 봅시다.
data2['Income_LY'] = 0
data2.head()
Attr | Age | Dist | EmpNo | Gen | JobSat | Marital | M_Income | OT | PctSalHike | TotWY | Income_LY | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 33 | 7 | 817 | Male | 3 | Married | 11691 | No | 11 | 14 | 0 |
1 | 0 | 35 | 18 | 1412 | Male | 4 | Single | 9362 | No | 11 | 10 | 0 |
2 | 0 | 42 | 6 | 1911 | Male | 1 | Married | 13348 | No | 13 | 18 | 0 |
3 | 0 | 46 | 2 | 1204 | Female | 1 | Married | 17048 | No | 23 | 28 | 0 |
4 | 1 | 22 | 4 | 593 | Male | 3 | Single | 3894 | No | 16 | 4 | 0 |
조건에 의한 값 변경 1
1
2
3
# M_Income 의 값이 1000보다 작은 경우, 0로 변경해 봅시다.
data2.loc[data2['M_Income'] < 4000, 'M_Income' ] = 0
data2.head()
Attr | Age | Dist | EmpNo | Gen | JobSat | Marital | M_Income | OT | PctSalHike | TotWY | Income_LY | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 33 | 7 | 817 | Male | 3 | Married | 11691 | No | 11 | 14 | 0 |
1 | 0 | 35 | 18 | 1412 | Male | 4 | Single | 9362 | No | 11 | 10 | 0 |
2 | 0 | 42 | 6 | 1911 | Male | 1 | Married | 13348 | No | 13 | 18 | 0 |
3 | 0 | 46 | 2 | 1204 | Female | 1 | Married | 17048 | No | 23 | 28 | 0 |
4 | 1 | 22 | 4 | 593 | Male | 3 | Single | 0 | No | 16 | 4 | 0 |
조건에 의한 값 변경 2
- 이번에는,
np.where()
를 이용해보자.
1
2
3
# Age가 40보다 많으면 1, 아니면 0으로 바꿔 봅시다.
data2['Age'] = np.where(data2['Age'] > 40, 1, 0)
data2.head()
Attr | Age | Dist | EmpNo | Gen | JobSat | Marital | M_Income | OT | PctSalHike | TotWY | Income_LY | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 7 | 817 | Male | 3 | Married | 11691 | No | 11 | 14 | 0 |
1 | 0 | 0 | 18 | 1412 | Male | 4 | Single | 9362 | No | 11 | 10 | 0 |
2 | 0 | 1 | 6 | 1911 | Male | 1 | Married | 13348 | No | 13 | 18 | 0 |
3 | 0 | 1 | 2 | 1204 | Female | 1 | Married | 17048 | No | 23 | 28 | 0 |
4 | 1 | 0 | 4 | 593 | Male | 3 | Single | 0 | No | 16 | 4 | 0 |
값 변경 2 (map, cut)
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()
Attr | Age | Dist | EmpNo | Gen | JobSat | Marital | M_Income | OT | PctSalHike | TotWY | Income_LY | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 33 | 7 | 817 | 1 | 3 | Married | 11691 | No | 11 | 14 | 10532.0 |
1 | 0 | 35 | 18 | 1412 | 1 | 4 | Single | 9362 | No | 11 | 10 | 8434.0 |
2 | 0 | 42 | 6 | 1911 | 1 | 1 | Married | 13348 | No | 13 | 18 | 11812.0 |
3 | 0 | 46 | 2 | 1204 | 0 | 1 | Married | 17048 | No | 23 | 28 | 13860.0 |
4 | 1 | 22 | 4 | 593 | 1 | 3 | Single | 3894 | No | 16 | 4 | 3357.0 |
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.