[KT Aivle 3기 AI] 4일차. (3) Pandas
1. 개요
KT Aivle School 3기 AI 4일차
- 주제 : Pandas
- 강사 : 한기영 강사님
- 내용 : Python Library 중 하나인 Pandas에 대하여 설명해주셨다. 대학교에서 수업 때 배운 적이 있어 수월하게 배울 수 있었다. 이전에 내가 정리해놓은 것과 함께 이번 수업내용을 토대로 Pandas에 대해 정리해보려 한다.
2. Pandas
- 구조화된 데이터 처리를 지원하는 Python 라이브러리
- 고성능 array 계산 라이브러리인 Numpy와 통합하여, 강력한 스프레드시트처리 기능을 제공
- 인덱싱, 연산용 함수, 전처리 함수 등을 제공함
- 데이터 처리 및 통계 분석을 위해 사용
1) Series
- 하나의 정보에 대한 데이터들의 집합
- index가 추가된 numpy
- 데이터 프레임에서 하나의 열을 떼어낸 것.(1차원)
1
2
3
4
5
6
7
from pandas import Series, DataFrame
import pandas as pd
import numpy as np
list_data = [1,2,3,4,5]
example_obj = Series(data = list_data)
example_obj
1
2
3
4
5
6
0 1
1 2
2 3
3 4
4 5
dtype: int64
1
2
3
4
list_data = [1,2,3,4,5]
list_name = ["a","b","c","d","e"]
example_obj = Series(data = list_data, index = list_name)
example_obj
1
2
3
4
5
6
a 1
b 2
c 3
d 4
e 5
dtype: int64
1
2
3
dic_data = {"a":1 , "b":2, "c":3, "d":4, "e":5}
example_obj = Series(dic_data, dtype=np.float32, name="example_data")
example_obj
1
2
3
4
5
6
a 1.0
b 2.0
c 3.0
d 4.0
e 5.0
Name: example_data, dtype: float32
1
example_obj["a"]
1
1.0
1
example_obj.values
1
array([1., 2., 3., 4., 5.], dtype=float32)
1
example_obj.index
1
Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
1
2
3
example_obj.name = "number"
example_obj.index.name = "alphabet"
example_obj
1
2
3
4
5
6
7
alphabet
a 1.0
b 2.0
c 3.0
d 4.0
e 5.0
Name: number, dtype: float32
2) DataFrame
- 데이터 분석에서 가장 중요한 데이터 구조
- 관계형 데이터베이스의 테이블 또는 엑셀 시트와 같은 형태(2차원 구조)
- 변수들의 집합 -> 각 열을 변수라고 부름
- 행 -> 의미 : 분석단위, 다른 말로 : 관측치, 샘플
- 열 -> 의미 : 정보, 다른 말로 : 변수(feature, target)
- Pandas 사용 목적이 데이터프레임을 사용하기 위한 목적으로 봐도 된다.
- 데이터를 처리, 조회, 분석하는 가장 효율적인 방법이 데이터프레임을 사용하는 것
- 일반적으로 접하게 되는 테이블 형태, 엑셀 형태로 생각하면 된다.
- 직접 만들 수 있으나 보통은 csv 파일, 엑셀 파일 또는 DB에서 온다.
(1) DataFrame 생성
1
2
3
4
5
6
raw_data = {'first_name': ['Jason', 'Molly', 'Tina', 'Jake', 'Amy'],
'last_name': ['Miller', 'Jacobson', 'Ali', 'Milner', 'Cooze'],
'age': [42, 52, 36, 24, 73],
'city': ['San Francisco', 'Baltimore', 'Miami', 'Douglas', 'Boston']}
df = pd.DataFrame(raw_data, columns = ['first_name', 'last_name', 'age', 'city'])
df
first_name | last_name | age | city | |
---|---|---|---|---|
0 | Jason | Miller | 42 | San Francisco |
1 | Molly | Jacobson | 52 | Baltimore |
2 | Tina | Ali | 36 | Miami |
3 | Jake | Milner | 24 | Douglas |
4 | Amy | Cooze | 73 | Boston |
(2) CSV파일 읽어오기
[1] csv 파일로 부터 가져오기
1
2
3
4
5
# 데이터 읽어오기
data = pd.read_csv('airquality_simple.csv')
# 상위 3행만 확인
data.head(3)
Ozone | Solar.R | Wind | Temp | Month | Day | |
---|---|---|---|---|---|---|
0 | 41 | 190.0 | 7.4 | 67 | 5 | 1 |
1 | 36 | 118.0 | 8.0 | 72 | 5 | 2 |
2 | 12 | 149.0 | 12.6 | 74 | 5 | 3 |
[2] url로 가져오기
1
2
3
4
5
6
# 데이터 읽어오기
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 |
(3) DataFrame 탐색
- 파일에서 불러온 데이터의 크기, 내용, 분포, 누락된 값 등을 확인
- 확인된 내용을 통해 데이터 전처리 필요 여부를 결정
- 데이터를 알아야 데이터를 분석할 수 있다!
[참고] 자주 사용할 만한 메서드들
- head(): 상위 데이터 확인
- tail(): 하위 데이터 확인
- shape: 데이터프레임 크기
- index: 인덱스 정보 확인
- values: 값 정보 확인
- columns: 열 정보 확인
- dtypes: 열 자료형 확인
- info(): 열에 대한 상세한 정보 확인
- describe(): 기초통계정보 확인
[1] 상위, 하위 일부 데이터, 크기 확인
head(n)
,tail(n)
메소드를 사용해 앞 뒤 데이터를 확인- 개수를 지정하지 않으면 기본적으로 5개 행이 조회 됨
1) 상위 데이터 확인
1
data.head()
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 |
3 | 0 | 46 | 2 | 1204 | Female | 1 | Married | 17048 | No | 23 | 28 |
4 | 1 | 22 | 4 | 593 | Male | 3 | Single | 3894 | No | 16 | 4 |
2) 하위 데이터 확인
1
data.tail(3)
Attrition | Age | DistanceFromHome | EmployeeNumber | Gender | JobSatisfaction | MaritalStatus | MonthlyIncome | OverTime | PercentSalaryHike | TotalWorkingYears | |
---|---|---|---|---|---|---|---|---|---|---|---|
1193 | 0 | 29 | 9 | 1558 | Male | 3 | Married | 2451 | No | 18 | 5 |
1194 | 0 | 29 | 2 | 469 | Male | 3 | Married | 4649 | No | 14 | 4 |
1195 | 0 | 43 | 16 | 327 | Female | 4 | Married | 16064 | Yes | 22 | 22 |
3) 크기 확인 .shape
- (rows, cols) 값을 갖는 튜플 형태로 확인이 가능
- 데이터를 분석할 때 처리할 데이터 양을 확인하는 목적으로 많이 사용
1
data.shape
1
(1196, 11)
[2] 열, 행 정보 보기
1) 열 확인
1
2
3
print(data.columns)
print()
print(data.columns.values) # np array 형태
1
2
3
4
5
6
7
8
Index(['Attrition', 'Age', 'DistanceFromHome', 'EmployeeNumber', 'Gender',
'JobSatisfaction', 'MaritalStatus', 'MonthlyIncome', 'OverTime',
'PercentSalaryHike', 'TotalWorkingYears'],
dtype='object')
['Attrition' 'Age' 'DistanceFromHome' 'EmployeeNumber' 'Gender'
'JobSatisfaction' 'MaritalStatus' 'MonthlyIncome' 'OverTime'
'PercentSalaryHike' 'TotalWorkingYears']
1
2
# 데이터프레임을 리스트 함수에 넣으면 열 이름이 리스트로 반환됨.
list(data)
1
2
3
4
5
6
7
8
9
10
11
['Attrition',
'Age',
'DistanceFromHome',
'EmployeeNumber',
'Gender',
'JobSatisfaction',
'MaritalStatus',
'MonthlyIncome',
'OverTime',
'PercentSalaryHike',
'TotalWorkingYears']
2) 자료형 확인
- int64: 정수형 데이터(int)
- float64: 실수형 데이터(float)
- object: 문자열 데이터(string)
1
data.dtypes
1
2
3
4
5
6
7
8
9
10
11
12
Attrition int64
Age int64
DistanceFromHome int64
EmployeeNumber int64
Gender object
JobSatisfaction int64
MaritalStatus object
MonthlyIncome int64
OverTime object
PercentSalaryHike int64
TotalWorkingYears int64
dtype: object
1
2
# 열 자료형, 값 개수 확인
data.info()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1196 entries, 0 to 1195
Data columns (total 11 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Attrition 1196 non-null int64
1 Age 1196 non-null int64
2 DistanceFromHome 1196 non-null int64
3 EmployeeNumber 1196 non-null int64
4 Gender 1196 non-null object
5 JobSatisfaction 1196 non-null int64
6 MaritalStatus 1196 non-null object
7 MonthlyIncome 1196 non-null int64
8 OverTime 1196 non-null object
9 PercentSalaryHike 1196 non-null int64
10 TotalWorkingYears 1196 non-null int64
dtypes: int64(8), object(3)
memory usage: 102.9+ KB
3) 기초통계정보 확인
- describe() 메소드는 데이터에 대한 많은 정보를 제공하는 매우 중요한 메소드이다.
- 개수(count), 평균(mean), 표준편차(std), 최솟값(min), 사분위값(25%, 50%, 75%), 최댓값(max)을 표시한다.
1
data.describe()
Attrition | Age | DistanceFromHome | EmployeeNumber | JobSatisfaction | MonthlyIncome | PercentSalaryHike | TotalWorkingYears | |
---|---|---|---|---|---|---|---|---|
count | 1196.000000 | 1196.00000 | 1196.000000 | 1196.000000 | 1196.000000 | 1196.000000 | 1196.000000 | 1196.000000 |
mean | 0.163043 | 36.94398 | 9.258361 | 1035.629599 | 2.716555 | 6520.104515 | 15.251672 | 11.330268 |
std | 0.369560 | 9.09270 | 8.166016 | 604.340130 | 1.110962 | 4665.902253 | 3.625946 | 7.823821 |
min | 0.000000 | 18.00000 | 1.000000 | 1.000000 | 1.000000 | 1009.000000 | 11.000000 | 0.000000 |
25% | 0.000000 | 30.00000 | 2.000000 | 507.750000 | 2.000000 | 2928.250000 | 12.000000 | 6.000000 |
50% | 0.000000 | 36.00000 | 7.000000 | 1028.000000 | 3.000000 | 4973.500000 | 14.000000 | 10.000000 |
75% | 0.000000 | 43.00000 | 14.000000 | 1581.250000 | 4.000000 | 8420.500000 | 18.000000 | 15.000000 |
max | 1.000000 | 60.00000 | 29.000000 | 2068.000000 | 4.000000 | 19999.000000 | 25.000000 | 40.000000 |
- 일부 열에 대해서만 기초통계정보를 확인할 수 있다.
1
print(data[['Age', 'MonthlyIncome']].describe())
1
2
3
4
5
6
7
8
9
Age MonthlyIncome
count 1196.00000 1196.000000
mean 36.94398 6520.104515
std 9.09270 4665.902253
min 18.00000 1009.000000
25% 30.00000 2928.250000
50% 36.00000 4973.500000
75% 43.00000 8420.500000
max 60.00000 19999.000000
[3] 정렬해서 보기
- 인덱스를 기준으로 정렬하는 방법과 특정 열을 기준으로 정렬하는 방법이 있다.
- sort_values() 메소드로 특정 열을 기준으로 정렬.
- ascending 옵션을 설정해 오름차순, 내림차순을 설정할 수 있다.
- ascending=True: 오름차순 정렬(기본값)
- ascending=False: 내림차순 정렬
1
data.sort_values(by='MonthlyIncome', ascending=False)
Attrition | Age | DistanceFromHome | EmployeeNumber | Gender | JobSatisfaction | MaritalStatus | MonthlyIncome | OverTime | PercentSalaryHike | TotalWorkingYears | |
---|---|---|---|---|---|---|---|---|---|---|---|
240 | 0 | 52 | 1 | 259 | Male | 3 | Married | 19999 | No | 14 | 34 |
234 | 0 | 41 | 7 | 1035 | Female | 3 | Divorced | 19973 | No | 22 | 21 |
322 | 0 | 56 | 4 | 1191 | Female | 1 | Divorced | 19943 | No | 13 | 28 |
530 | 0 | 50 | 11 | 226 | Female | 2 | Single | 19926 | No | 15 | 21 |
532 | 1 | 55 | 2 | 787 | Male | 1 | Married | 19859 | Yes | 13 | 24 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
150 | 1 | 29 | 24 | 1928 | Male | 1 | Single | 1091 | No | 17 | 1 |
1118 | 1 | 30 | 9 | 1876 | Male | 4 | Single | 1081 | No | 13 | 1 |
709 | 0 | 28 | 10 | 1056 | Male | 2 | Married | 1052 | No | 22 | 1 |
862 | 0 | 18 | 5 | 1012 | Male | 4 | Single | 1051 | No | 15 | 0 |
91 | 1 | 20 | 10 | 701 | Male | 3 | Single | 1009 | Yes | 11 | 1 |
1196 rows × 11 columns
1
2
# 복합 열 정렬
data.sort_values(by=['JobSatisfaction', 'MonthlyIncome'], ascending=[True, False])
Attrition | Age | DistanceFromHome | EmployeeNumber | Gender | JobSatisfaction | MaritalStatus | MonthlyIncome | OverTime | PercentSalaryHike | TotalWorkingYears | |
---|---|---|---|---|---|---|---|---|---|---|---|
322 | 0 | 56 | 4 | 1191 | Female | 1 | Divorced | 19943 | No | 13 | 28 |
532 | 1 | 55 | 2 | 787 | Male | 1 | Married | 19859 | Yes | 13 | 24 |
273 | 0 | 58 | 1 | 1423 | Female | 1 | Married | 19701 | Yes | 21 | 32 |
418 | 0 | 60 | 7 | 549 | Female | 1 | Married | 19566 | No | 11 | 33 |
685 | 0 | 54 | 5 | 522 | Male | 1 | Married | 19406 | No | 11 | 24 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
197 | 0 | 31 | 2 | 1974 | Female | 4 | Divorced | 1129 | Yes | 11 | 1 |
386 | 1 | 25 | 24 | 1273 | Male | 4 | Single | 1118 | Yes | 14 | 1 |
684 | 1 | 19 | 2 | 243 | Male | 4 | Single | 1102 | No | 22 | 1 |
1118 | 1 | 30 | 9 | 1876 | Male | 4 | Single | 1081 | No | 13 | 1 |
862 | 0 | 18 | 5 | 1012 | Male | 4 | Single | 1051 | No | 15 | 0 |
1196 rows × 11 columns
1
2
3
# 복합 열 정렬 : 별도로 저장하고, 인덱스 reset
temp = data.sort_values(by=['JobSatisfaction', 'MonthlyIncome'], ascending=[True, False])
temp.reset_index(drop = True)
Attrition | Age | DistanceFromHome | EmployeeNumber | Gender | JobSatisfaction | MaritalStatus | MonthlyIncome | OverTime | PercentSalaryHike | TotalWorkingYears | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 56 | 4 | 1191 | Female | 1 | Divorced | 19943 | No | 13 | 28 |
1 | 1 | 55 | 2 | 787 | Male | 1 | Married | 19859 | Yes | 13 | 24 |
2 | 0 | 58 | 1 | 1423 | Female | 1 | Married | 19701 | Yes | 21 | 32 |
3 | 0 | 60 | 7 | 549 | Female | 1 | Married | 19566 | No | 11 | 33 |
4 | 0 | 54 | 5 | 522 | Male | 1 | Married | 19406 | No | 11 | 24 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
1191 | 0 | 31 | 2 | 1974 | Female | 4 | Divorced | 1129 | Yes | 11 | 1 |
1192 | 1 | 25 | 24 | 1273 | Male | 4 | Single | 1118 | Yes | 14 | 1 |
1193 | 1 | 19 | 2 | 243 | Male | 4 | Single | 1102 | No | 22 | 1 |
1194 | 1 | 30 | 9 | 1876 | Male | 4 | Single | 1081 | No | 13 | 1 |
1195 | 0 | 18 | 5 | 1012 | Male | 4 | Single | 1051 | No | 15 | 0 |
1196 rows × 11 columns
[4] 기본 집계
고유값 확인
unique()
메소드로 고유값을 확인하며, 결과값은 배열 형태
1
2
# MaritalStatus 열 고유값 확인
print(data['MaritalStatus'].unique())
1
['Married' 'Single' 'Divorced']
고유값과 개수 확인
- value_counts() 메소드로 고유값과 그 개수를 확인하며, 결과값은 시리즈 형태
1
2
# MaritalStatus 열 고유값 개수 확인
print(data['MaritalStatus'].value_counts())
1
2
3
4
Married 548
Single 384
Divorced 264
Name: MaritalStatus, dtype: int64
2) 기본 집계 메소드 사용
- 데이터를 1차 집계 한 후 분석을 진행하는 경우가 많으므로 필히 알아두어야 하는 내용
- 이후에 배우는 Groupby 기능에서 같이 사용됨
1
2
# MonthlyIncome 열 합계 조회
print(data['MonthlyIncome'].sum())
1
7798045
1
2
# MonthlyIncome 열 최댓값 조회
print(data['MonthlyIncome'].max())
1
19999
1
2
# 'Age', 'MonthlyIncome' 열 평균값 확인
print(data[['Age', 'MonthlyIncome']].mean())
1
2
3
Age 36.943980
MonthlyIncome 6520.104515
dtype: float64
1
2
# 'Age', 'MonthlyIncome' 열 중앙값 확인
print(data[['Age', 'MonthlyIncome']].median())
1
2
3
Age 36.0
MonthlyIncome 4973.5
dtype: float64
(4) DataFrame 조회
- 보고자 하는 데이터를 즉시 조회할 수 있도록 반복 학습과 실습을 통해 익숙해져야 함
- 데이터프레임을 대상으로 조회하는 방법은 다양하다.
- 그 중 한가지 방법을 선택해 일관되게 사용하기를 권고
[1] 특정 열 조회
- df.loc[:, [열 이름1, 열 이름2, … ]] 형태로 조회할 열 이름을 리스트로 지정
- 열부분은 생략할 수 있지만, 행 부분을 생략할 수는 없다.
- 하지만 df[[열 이름1, 열 이름2, …]] 형태로 인덱서를 생략함이 일반적이다.
- 조회할 열이 하나면 리스트 형태가 아니어도 된다.
1
2
# Attrition 열 조회 : 시리즈로 조회 (조금 더 권장하는 방법)
data['Attrition']
1
2
3
4
5
6
7
8
9
10
11
12
0 0
1 0
2 0
3 0
4 1
..
1191 0
1192 0
1193 0
1194 0
1195 0
Name: Attrition, Length: 1196, dtype: int64
1
2
# Attrition 열 조회2 : 시리즈로 조회 (오류 발생 가능성 있음)
data.Attrition
1
2
3
4
5
6
7
8
9
10
11
12
0 0
1 0
2 0
3 0
4 1
..
1191 0
1192 0
1193 0
1194 0
1195 0
Name: Attrition, Length: 1196, dtype: int64
1
2
3
# Attrition, Age 열 조회 : 데이터프레임으로 조회
# 대괄호 안에 리스트!!!
data[['Attrition', 'Age' ]]
Attrition | Age | |
---|---|---|
0 | 0 | 33 |
1 | 0 | 35 |
2 | 0 | 42 |
3 | 0 | 46 |
4 | 1 | 22 |
... | ... | ... |
1191 | 0 | 32 |
1192 | 0 | 27 |
1193 | 0 | 29 |
1194 | 0 | 29 |
1195 | 0 | 43 |
1196 rows × 2 columns
[2] 조건으로 조회
- df.loc[조건] 형태로 조건을 지정해 조건에 만족하는 데이터만 조회할 수 있다.
- 우선 조건이 제대로 판단이 되는지 확인한 후, 그 조건을 대괄호 안에 넣으면 된다.
1) 단일 조건 조회
1
2
# 조건절(조건문)의 결과는 True, False
data['DistanceFromHome'] > 10
1
2
3
4
5
6
7
8
9
10
11
12
0 False
1 True
2 False
3 False
4 False
...
1191 False
1192 True
1193 False
1194 False
1195 True
Name: DistanceFromHome, Length: 1196, dtype: bool
1
2
# DistanceFromHome 열 값이 10 보다 큰 행 조회
data.loc[data['DistanceFromHome'] > 10]
Attrition | Age | DistanceFromHome | EmployeeNumber | Gender | JobSatisfaction | MaritalStatus | MonthlyIncome | OverTime | PercentSalaryHike | TotalWorkingYears | |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 0 | 35 | 18 | 1412 | Male | 4 | Single | 9362 | No | 11 | 10 |
5 | 0 | 24 | 21 | 1551 | Male | 1 | Divorced | 2296 | No | 14 | 2 |
7 | 0 | 30 | 20 | 1084 | Male | 1 | Married | 9957 | No | 15 | 7 |
11 | 1 | 33 | 15 | 582 | Male | 3 | Married | 13610 | Yes | 12 | 15 |
15 | 0 | 34 | 23 | 60 | Male | 3 | Single | 4568 | No | 20 | 10 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
1181 | 0 | 35 | 28 | 1596 | Male | 3 | Married | 3407 | No | 17 | 10 |
1186 | 1 | 26 | 20 | 1818 | Female | 2 | Married | 2148 | Yes | 11 | 6 |
1188 | 0 | 29 | 19 | 1497 | Male | 3 | Divorced | 8620 | No | 14 | 10 |
1192 | 0 | 27 | 19 | 1619 | Male | 1 | Divorced | 4066 | No | 11 | 7 |
1195 | 0 | 43 | 16 | 327 | Female | 4 | Married | 16064 | Yes | 22 | 22 |
363 rows × 11 columns
2) 여러 조건 조회
1
2
# and로 여러 조건 연결
data.loc[(data['DistanceFromHome'] > 10) & (data['JobSatisfaction'] == 4)]
Attrition | Age | DistanceFromHome | EmployeeNumber | Gender | JobSatisfaction | MaritalStatus | MonthlyIncome | OverTime | PercentSalaryHike | TotalWorkingYears | |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 0 | 35 | 18 | 1412 | Male | 4 | Single | 9362 | No | 11 | 10 |
50 | 0 | 29 | 15 | 346 | Male | 4 | Single | 2340 | No | 19 | 6 |
51 | 0 | 45 | 28 | 1546 | Male | 4 | Married | 2132 | No | 20 | 8 |
64 | 0 | 32 | 15 | 1955 | Female | 4 | Divorced | 6667 | No | 18 | 9 |
82 | 1 | 35 | 12 | 1667 | Male | 4 | Single | 4581 | Yes | 24 | 13 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
1104 | 0 | 34 | 19 | 1701 | Female | 4 | Married | 2929 | No | 12 | 10 |
1126 | 0 | 35 | 11 | 1137 | Male | 4 | Divorced | 4968 | No | 11 | 5 |
1141 | 1 | 49 | 11 | 840 | Female | 4 | Married | 7654 | No | 18 | 9 |
1148 | 0 | 36 | 18 | 1133 | Male | 4 | Single | 7779 | No | 20 | 18 |
1195 | 0 | 43 | 16 | 327 | Female | 4 | Married | 16064 | Yes | 22 | 22 |
107 rows × 11 columns
1
2
# or 조건 : |
data.loc[(data['DistanceFromHome'] > 10) | (data['JobSatisfaction'] == 4)]
Attrition | Age | DistanceFromHome | EmployeeNumber | Gender | JobSatisfaction | MaritalStatus | MonthlyIncome | OverTime | PercentSalaryHike | TotalWorkingYears | |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 0 | 35 | 18 | 1412 | Male | 4 | Single | 9362 | No | 11 | 10 |
5 | 0 | 24 | 21 | 1551 | Male | 1 | Divorced | 2296 | No | 14 | 2 |
7 | 0 | 30 | 20 | 1084 | Male | 1 | Married | 9957 | No | 15 | 7 |
8 | 0 | 26 | 6 | 686 | Female | 4 | Married | 2659 | Yes | 13 | 3 |
11 | 1 | 33 | 15 | 582 | Male | 3 | Married | 13610 | Yes | 12 | 15 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
1186 | 1 | 26 | 20 | 1818 | Female | 2 | Married | 2148 | Yes | 11 | 6 |
1188 | 0 | 29 | 19 | 1497 | Male | 3 | Divorced | 8620 | No | 14 | 10 |
1190 | 0 | 27 | 5 | 844 | Male | 4 | Divorced | 12808 | Yes | 16 | 9 |
1192 | 0 | 27 | 19 | 1619 | Male | 1 | Divorced | 4066 | No | 11 | 7 |
1195 | 0 | 43 | 16 | 327 | Female | 4 | Married | 16064 | Yes | 22 | 22 |
629 rows × 11 columns
3) isin()
, between()
isin([값1, 값2, ..., 값n])
: 값1 또는 값2 또는 .. 값n 인 데이터만 조회- 주의 :
isin(리스트)
값들을 리스트 형태로 입력해야 한다.
1
2
# 값 나열
data.loc[data['JobSatisfaction'].isin([1,4])]
Attrition | Age | DistanceFromHome | EmployeeNumber | Gender | JobSatisfaction | MaritalStatus | MonthlyIncome | OverTime | PercentSalaryHike | TotalWorkingYears | |
---|---|---|---|---|---|---|---|---|---|---|---|
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 |
5 | 0 | 24 | 21 | 1551 | Male | 1 | Divorced | 2296 | No | 14 | 2 |
7 | 0 | 30 | 20 | 1084 | Male | 1 | Married | 9957 | No | 15 | 7 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
1184 | 0 | 33 | 5 | 1395 | Male | 4 | Married | 9998 | No | 13 | 8 |
1185 | 0 | 24 | 10 | 1746 | Male | 4 | Married | 2145 | No | 14 | 3 |
1190 | 0 | 27 | 5 | 844 | Male | 4 | Divorced | 12808 | Yes | 16 | 9 |
1192 | 0 | 27 | 19 | 1619 | Male | 1 | Divorced | 4066 | No | 11 | 7 |
1195 | 0 | 43 | 16 | 327 | Female | 4 | Married | 16064 | Yes | 22 | 22 |
616 rows × 11 columns
- 위 구문은 다음과 같은 의미를 갖는다.
1
2
# or 조건
data.loc[(data['JobSatisfaction'] == 1) | (data['JobSatisfaction'] == 4)]
Attrition | Age | DistanceFromHome | EmployeeNumber | Gender | JobSatisfaction | MaritalStatus | MonthlyIncome | OverTime | PercentSalaryHike | TotalWorkingYears | |
---|---|---|---|---|---|---|---|---|---|---|---|
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 |
5 | 0 | 24 | 21 | 1551 | Male | 1 | Divorced | 2296 | No | 14 | 2 |
7 | 0 | 30 | 20 | 1084 | Male | 1 | Married | 9957 | No | 15 | 7 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
1184 | 0 | 33 | 5 | 1395 | Male | 4 | Married | 9998 | No | 13 | 8 |
1185 | 0 | 24 | 10 | 1746 | Male | 4 | Married | 2145 | No | 14 | 3 |
1190 | 0 | 27 | 5 | 844 | Male | 4 | Divorced | 12808 | Yes | 16 | 9 |
1192 | 0 | 27 | 19 | 1619 | Male | 1 | Divorced | 4066 | No | 11 | 7 |
1195 | 0 | 43 | 16 | 327 | Female | 4 | Married | 16064 | Yes | 22 | 22 |
616 rows × 11 columns
between(값1, 값2)
: 값1 ~ 값2 까지 범위안의 데이터만 조회
1
2
# 범위 지정
data.loc[data['Age'].between(25, 30)]
Attrition | Age | DistanceFromHome | EmployeeNumber | Gender | JobSatisfaction | MaritalStatus | MonthlyIncome | OverTime | PercentSalaryHike | TotalWorkingYears | |
---|---|---|---|---|---|---|---|---|---|---|---|
7 | 0 | 30 | 20 | 1084 | Male | 1 | Married | 9957 | No | 15 | 7 |
8 | 0 | 26 | 6 | 686 | Female | 4 | Married | 2659 | Yes | 13 | 3 |
16 | 0 | 30 | 5 | 197 | Female | 1 | Divorced | 3204 | No | 14 | 8 |
28 | 0 | 26 | 1 | 1893 | Female | 3 | Married | 2933 | Yes | 13 | 1 |
32 | 0 | 30 | 7 | 1224 | Male | 3 | Divorced | 3491 | No | 13 | 10 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
1188 | 0 | 29 | 19 | 1497 | Male | 3 | Divorced | 8620 | No | 14 | 10 |
1190 | 0 | 27 | 5 | 844 | Male | 4 | Divorced | 12808 | Yes | 16 | 9 |
1192 | 0 | 27 | 19 | 1619 | Male | 1 | Divorced | 4066 | No | 11 | 7 |
1193 | 0 | 29 | 9 | 1558 | Male | 3 | Married | 2451 | No | 18 | 5 |
1194 | 0 | 29 | 2 | 469 | Male | 3 | Married | 4649 | No | 14 | 4 |
238 rows × 11 columns
- 위 구문은 다음과 같은 의미를 갖는다.
1
2
# and 조건
data.loc[(data['Age'] >= 25) & (data['Age'] <= 30)]
Attrition | Age | DistanceFromHome | EmployeeNumber | Gender | JobSatisfaction | MaritalStatus | MonthlyIncome | OverTime | PercentSalaryHike | TotalWorkingYears | |
---|---|---|---|---|---|---|---|---|---|---|---|
7 | 0 | 30 | 20 | 1084 | Male | 1 | Married | 9957 | No | 15 | 7 |
8 | 0 | 26 | 6 | 686 | Female | 4 | Married | 2659 | Yes | 13 | 3 |
16 | 0 | 30 | 5 | 197 | Female | 1 | Divorced | 3204 | No | 14 | 8 |
28 | 0 | 26 | 1 | 1893 | Female | 3 | Married | 2933 | Yes | 13 | 1 |
32 | 0 | 30 | 7 | 1224 | Male | 3 | Divorced | 3491 | No | 13 | 10 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
1188 | 0 | 29 | 19 | 1497 | Male | 3 | Divorced | 8620 | No | 14 | 10 |
1190 | 0 | 27 | 5 | 844 | Male | 4 | Divorced | 12808 | Yes | 16 | 9 |
1192 | 0 | 27 | 19 | 1619 | Male | 1 | Divorced | 4066 | No | 11 | 7 |
1193 | 0 | 29 | 9 | 1558 | Male | 3 | Married | 2451 | No | 18 | 5 |
1194 | 0 | 29 | 2 | 469 | Male | 3 | Married | 4649 | No | 14 | 4 |
238 rows × 11 columns
4) 조건을 만족하는 행의 일부 열 조회
df.loc[조건, ['열 이름1', '열 이름2', ...]]
형태로 조회할 열을 리스트로 지정 => 2차원, 데이터프레임 형태로 조회
1
2
# 조건에 맞는 하나의 열 조회
data.loc[data['MonthlyIncome'] >= 10000, ['Age']]
Age | |
---|---|
0 | 33 |
2 | 42 |
3 | 46 |
11 | 33 |
13 | 39 |
... | ... |
1157 | 42 |
1158 | 54 |
1166 | 34 |
1190 | 27 |
1195 | 43 |
230 rows × 1 columns
1
2
# 조건에 맞는 여러 열 조회
data.loc[data['MonthlyIncome'] >= 10000, ['Age', 'MaritalStatus', 'TotalWorkingYears']]
Age | MaritalStatus | TotalWorkingYears | |
---|---|---|---|
0 | 33 | Married | 14 |
2 | 42 | Married | 18 |
3 | 46 | Married | 28 |
11 | 33 | Married | 15 |
13 | 39 | Single | 21 |
... | ... | ... | ... |
1157 | 42 | Single | 24 |
1158 | 54 | Married | 36 |
1166 | 34 | Single | 14 |
1190 | 27 | Divorced | 9 |
1195 | 43 | Married | 22 |
230 rows × 3 columns
연습문제
- MaritalStatus 가 Single 이고, 나이가 30~40 인 직원을 월급순으로 정렬 (내림차순)
1
data.loc[(data['MaritalStatus'] == 'Single') & (data['Age'].between(30, 40))].sort_values(['MonthlyIncome'], ascending=False)
Attrition | Age | DistanceFromHome | EmployeeNumber | Gender | JobSatisfaction | MaritalStatus | MonthlyIncome | OverTime | PercentSalaryHike | TotalWorkingYears | |
---|---|---|---|---|---|---|---|---|---|---|---|
1092 | 0 | 40 | 7 | 1740 | Male | 2 | Single | 19833 | No | 14 | 21 |
467 | 0 | 40 | 14 | 1128 | Male | 3 | Single | 19626 | No | 14 | 21 |
13 | 0 | 39 | 9 | 2022 | Male | 4 | Single | 19431 | No | 13 | 21 |
265 | 0 | 31 | 8 | 1430 | Female | 2 | Single | 16422 | No | 11 | 9 |
420 | 0 | 40 | 9 | 1166 | Female | 3 | Single | 13499 | No | 17 | 20 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
46 | 0 | 36 | 3 | 238 | Male | 2 | Single | 2088 | No | 12 | 13 |
568 | 0 | 36 | 7 | 1659 | Male | 2 | Single | 2013 | No | 11 | 15 |
26 | 1 | 32 | 2 | 1692 | Male | 2 | Single | 1393 | No | 12 | 1 |
301 | 1 | 31 | 8 | 1433 | Female | 2 | Single | 1261 | No | 12 | 1 |
1118 | 1 | 30 | 9 | 1876 | Male | 4 | Single | 1081 | No | 13 | 1 |
175 rows × 11 columns
5) 기타
(1) loc와 iloc
loc
는 index 이름,iloc
는 index number 기준으로 탐색
1
2
s = pd.Series(np.nan, index=[49,48,47,46,45, 1, 2, 3, 4, 5])
s.loc[:3]
1
2
3
4
5
6
7
8
9
49 NaN
48 NaN
47 NaN
46 NaN
45 NaN
1 NaN
2 NaN
3 NaN
dtype: float64
1
s.iloc[:3]
1
2
3
4
49 NaN
48 NaN
47 NaN
dtype: float64
(2) isnull()
- column 또는 row 값의 NaN(null) 값의 index를 반환함
1
data.isnull().head()
Attrition | Age | DistanceFromHome | EmployeeNumber | Gender | JobSatisfaction | MaritalStatus | MonthlyIncome | OverTime | PercentSalaryHike | TotalWorkingYears | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | False | False | False | False | False | False | False | False | False | False | False |
1 | False | False | False | False | False | False | False | False | False | False | False |
2 | False | False | False | False | False | False | False | False | False | False | False |
3 | False | False | False | False | False | False | False | False | False | False | False |
4 | False | False | False | False | False | False | False | False | False | False | False |
1
data.isnull().sum()
1
2
3
4
5
6
7
8
9
10
11
12
Attrition 0
Age 0
DistanceFromHome 0
EmployeeNumber 0
Gender 0
JobSatisfaction 0
MaritalStatus 0
MonthlyIncome 0
OverTime 0
PercentSalaryHike 0
TotalWorkingYears 0
dtype: int64
(3) 기타 메소드
df.T
: Transposedf.values
: 값 출력df.to_csv()
: csv 변환del df["debt"]
: column 삭제df.cumsum()
: 누적 합df.cummax()
: 누적 최대df.cummin()
: 누적 최소
(5) DataFrame 수정
[1] Index 변경
1
df
first_name | last_name | age | city | |
---|---|---|---|---|
0 | Jason | Miller | 42 | San Francisco |
1 | Molly | Jacobson | 52 | Baltimore |
2 | Tina | Ali | 36 | Miami |
3 | Jake | Milner | 24 | Douglas |
4 | Amy | Cooze | 73 | Boston |
1
2
df.index = df['first_name']
df
first_name | last_name | age | city | |
---|---|---|---|---|
first_name | ||||
Jason | Jason | Miller | 42 | San Francisco |
Molly | Molly | Jacobson | 52 | Baltimore |
Tina | Tina | Ali | 36 | Miami |
Jake | Jake | Milner | 24 | Douglas |
Amy | Amy | Cooze | 73 | Boston |
[2] 열 삭제
1
2
del df['first_name']
df
last_name | age | city | |
---|---|---|---|
first_name | |||
Jason | Miller | 42 | San Francisco |
Molly | Jacobson | 52 | Baltimore |
Tina | Ali | 36 | Miami |
Jake | Milner | 24 | Douglas |
Amy | Cooze | 73 | Boston |
[3] Index 재설정
1
df.reset_index()
first_name | last_name | age | city | |
---|---|---|---|---|
0 | Jason | Miller | 42 | San Francisco |
1 | Molly | Jacobson | 52 | Baltimore |
2 | Tina | Ali | 36 | Miami |
3 | Jake | Milner | 24 | Douglas |
4 | Amy | Cooze | 73 | Boston |
[4] Data Drop
1
df.drop('city', axis=1)
last_name | age | |
---|---|---|
first_name | ||
Jason | Miller | 42 |
Molly | Jacobson | 52 |
Tina | Ali | 36 |
Jake | Milner | 24 |
Amy | Cooze | 73 |
1
df
last_name | age | city | |
---|---|---|---|
first_name | |||
Jason | Miller | 42 | San Francisco |
Molly | Jacobson | 52 | Baltimore |
Tina | Ali | 36 | Miami |
Jake | Milner | 24 | Douglas |
Amy | Cooze | 73 | Boston |
1
2
# 여러개 없애기
df.drop(['city', 'age'], axis=1)
last_name | |
---|---|
first_name | |
Jason | Miller |
Molly | Jacobson |
Tina | Ali |
Jake | Milner |
Amy | Cooze |
(6) DataFrame 집계
- 상세 데이터가 아닌 집계된 데이터에 대한 분석을 자주 요구하니 익숙해져야 할 내용임.
- sum(), mean(), max(), min(), count() 메소드를 사용해 지정한 열 또는 열들을 기준으로 집계한다.
[1] Groupby
df.groupby(['집계기준변수'], as_index=)['집계대상변수'].집계함수
- 집계기준변수 : ~~별에 해당되는 변수 혹은 리스트. 범주형 변수 (ex: 월 별, 지역 별 등)
- 집계대상변수 : 집계함수로 집계할 변수 혹은 리스트. (ex: 매출액 합계)
- as_index = True (Default)
- 집계기준변수를 인덱스로 사용
1
2
3
4
5
6
# 데이터 읽어오기
path = 'https://raw.githubusercontent.com/DA4BAM/dataset/master/Attrition_simple2.CSV'
data = pd.read_csv(path)
# 상위 5개 확인
data.head(5)
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 |
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) 열 하나 집계
1
2
# MonthlyIncome 합계
data['MonthlyIncome'].sum()
1
7798045
1
2
# MonthlyIncome, TotalWorkingYears 각각의 평균
data[['MonthlyIncome', 'TotalWorkingYears']].mean()
1
2
3
MonthlyIncome 6520.104515
TotalWorkingYears 11.330268
dtype: float64
1
2
# MaritalStatus 별 Age 평균 --> 시리즈
data.groupby('MaritalStatus', as_index=True)['Age'].mean()
1
2
3
4
5
MaritalStatus
Divorced 37.522727
Married 37.704380
Single 35.460938
Name: Age, dtype: float64
1
2
# MaritalStatus 별 Age 평균 --> 데이터프레임
data.groupby('MaritalStatus', as_index=True)[['Age']].mean()
Age | |
---|---|
MaritalStatus | |
Divorced | 37.522727 |
Married | 37.704380 |
Single | 35.460938 |
1
2
# MaritalStatus 별 Age 평균 --> 데이터프레임
data.groupby('MaritalStatus', as_index=False)[['Age']].mean()
MaritalStatus | Age | |
---|---|---|
0 | Divorced | 37.522727 |
1 | Married | 37.704380 |
2 | Single | 35.460938 |
1
2
3
4
data_mean = data.groupby('MaritalStatus', as_index=False)[['Age']].mean()
# 확인
data_mean
MaritalStatus | Age | |
---|---|---|
0 | Divorced | 37.522727 |
1 | Married | 37.704380 |
2 | Single | 35.460938 |
2) 여러 열 집계
1
2
3
4
data_mean = data.groupby('MaritalStatus', as_index=False)[['Age','MonthlyIncome']].mean()
# 확인
data_mean
MaritalStatus | Age | MonthlyIncome | |
---|---|---|---|
0 | Divorced | 37.522727 | 6707.018939 |
1 | Married | 37.704380 | 6880.144161 |
2 | Single | 35.460938 | 5877.794271 |
- sum() 메소드 앞에 아무 열도 지정하지 않으면 기준열 이외의 모든 열에 대한 집계가 수행됩니다.
1
2
3
4
data_sum = data.groupby('MaritalStatus', as_index=False).sum()
# 확인
data_sum
MaritalStatus | Attrition | Age | DistanceFromHome | EmployeeNumber | JobSatisfaction | MonthlyIncome | PercentSalaryHike | TotalWorkingYears | |
---|---|---|---|---|---|---|---|---|---|
0 | Divorced | 23 | 9906 | 2404 | 266305 | 716 | 1770653 | 3958 | 3106 |
1 | Married | 69 | 20662 | 5295 | 584446 | 1468 | 3770319 | 8431 | 6470 |
2 | Single | 103 | 13617 | 3374 | 387862 | 1065 | 2257073 | 5852 | 3975 |
- by=[‘feature1’, ‘feature2’] 과 같이 집계 기준 열을 여럿 설정할 수도 있습니다.
1
2
3
4
5
# 'MaritalStatus', 'Gender'별 나머지 열들 평균 조회
data_sum = data.groupby(['MaritalStatus', 'Gender'], as_index=False)[['Age','MonthlyIncome']].mean()
# 확인
data_sum
MaritalStatus | Gender | Age | MonthlyIncome | |
---|---|---|---|---|
0 | Divorced | Female | 37.010526 | 6626.315789 |
1 | Divorced | Male | 37.810651 | 6752.384615 |
2 | Married | Female | 38.774194 | 7301.493088 |
3 | Married | Male | 37.003021 | 6603.912387 |
4 | Single | Female | 35.261146 | 5963.445860 |
5 | Single | Male | 35.599119 | 5818.555066 |
[2] Aggregation
- df.groupby( ).agg([‘함수1’,’함수2’, …])
- 여러 함수로 한꺼번에 집계
- as_index 예외 :
.agg()
를 사용하면as_index = False
해도, ~~별 칼럼이 인덱스로 들어간다.
1
2
3
data_agg = data.groupby('MaritalStatus', as_index=False)[['MonthlyIncome']].agg(['min','max','mean'])
# 확인
data_agg
MonthlyIncome | |||
---|---|---|---|
min | max | mean | |
MaritalStatus | |||
Divorced | 1129 | 19973 | 6707.018939 |
Married | 1052 | 19999 | 6880.144161 |
Single | 1009 | 19926 | 5877.794271 |
This post is licensed under CC BY 4.0 by the author.