분석할 데이터를 확보하면 가장 먼저 데이터의 특징을 파악하고 다루기 쉽게 변형하는 작업을 해야 함.
이 장에서는 데이터를 다루는 기초적인 방법을 익힘.
05-1 데이터 파악하기
데이터가 주어졌을 때 가장 먼저 하는 일은 데이터의 전반적인 구조를 파악하는 것임.
어떤 변수들이 있는지, 몇 행으로 구성되는 지 구조를 살펴보면서 데이터의 특징이 어떠한지 감을 잡음.
이 과정에서 분석 방향의 힌트를 얻게 됨.
데이터를 파악할 때 사용하는 명령어
- 데이터를 파악할 때는 기본적으로 다음 여섯 가지 명령어를 사용함.
함수 | 기능 |
head() | 앞부분 출력 |
tail() | 뒷부분 출력 |
shape | 행, 열 개수 출력 |
info() | 변수 속성 출력 |
describe() | 요약 통계량 출력 |
- 4장에서 사용한 exam.csv파일을 활용해 데이터를 파악하는 방법을 알아보겠음.
- 먼저 exam.csv 파일을 불러와 데이터 프레임을 만들겠음.
import pandas as pd
exam = pd.read_csv('exam.csv')
[Do it! 실습] 데이터 입력해 데이터 프레임 만들기
head() - 데이터 앞부분 확인하기
- “head()”는 데이터의 앞에서부터 다섯 번째 행까지 출력하는 기능을 함. head()를 이용해 데이터의 앞부분 일부를 출력하면 데이터의 형태를 쉽게 확인할 수 있음.
- exam.head()처럼 변수 뒤에 점을 찍어 사용하는 함수를 메서드(method)라고 함.
exam.head()
- 괄호에 숫자를 입력하면 입력한 행까지 데이터를 출력함.
exam.head(10) # 앞에서부터 10행까지 출력
tail() - 데이터 뒷부분 확인하기
- tail()은 데이터의 뒷부분을 출력하는 기능을 함.
- head()와 반대로 뒤에서부터 다섯 번째 행까지 출력함.
exam.tail()
- head()와 마찬가지로 괄호에 숫자를 입력하면 뒤에서부터 입력한 행까지 출력함.
exam.tail(10) # 뒤에서부터 10행까지 출력
shape - 데이터가 몇 행, 몇 열로 구성되는지 알아보기
- shape는 데이터 프레임의 크기를 알아볼 때 사용함.
- 데이터 프레임에 점을 찍고 shape를 추가하면 데이터 프레임의 행, 열 개수를 출력함.
- 출력된 숫자 2개 중에서 앞은 ‘행’, 뒤는 ‘열’의 개수를 나타냄.
- 하나의 행이 한 학생의 시험 성적을 의미하므로, exam 데이터가 학생 20명에 대한 5개의 변수로 구성된다는 것을 알 수 있음.
exam.shape
# output: (20, 5)
- shape는 함수가 아니라 데이터 프레임이 가지고 있는 속성인 어트리뷰트(attribute)임.
- 어트리뷰트를 출력할 때는 명령어 뒤에 괄호를 입력하지 않으니 주의바람.
info() - 변수 속성 파악하기
- info()는 데이터에 들어 있는 변수들의 속성을 보여줌.
- 모든 변수의 속성을 한눈에 파악하고 싶을 때 info()를 사용함.
exam.info()
info()는 출력 결과를 보면 다음과 같은 사실을 알 수 있음.
➊ 첫 번째 행의 pandas.core.frame.DataFrame을 보면 exam이 pandas로 만든 데이터 프레임이라는 것을 알 수 있음.
➋ 두 번째 행의 20 entries, 0 to 19을 보면 exam이 20행으로 되어 있고, 행 번호는 0부터 19까지라는 것을 알 수 있음.
➌ 세 번째 행의 total 5 columns를 exam보면 이 변수 5개로 구성된다는 것을 알 수 있음.
➍ 여섯 번째 행부터 데이터 프레임에 들어 있는 변수들의 속성이 표시됨. 각 행에 변수 순서(#), 이름(Column), 변수에 들어 있는 값의 개수(Non-Null Count), 속성(Dtype)을 보여줌. 예를 들어 0번째 변수 id를 보면 20개의 값이 있고 정수(int64)로 된 변수라는 것을 알 수 있음. 변수의 속성은 정수(int64)외에도 실수(float64), 문자(object), 날짜 시간(datatime64) 등이 있음.
변수 속성 뒤에 붙은 64는 변수가 64비트로 되어 있다는 의미임. 1비트로 두 개의 값을 표현할 수 있으므로 int64는 2^64개의 정수를 표현할 수 있음.
Non-Null Count는 결측치(누락된 값)를 제외하고 구한 값의 개수를 나타냄. 결측치는 7장에서 다룸.
describe() - 요약 통계량 구하기
- describe()는 ‘평균’처럼 변수의 값을 요약한 ‘요약 통계량’을 구하는 함수임.
- 요약 통계량을 보면 변수의 특징을 파악하는데 도움이 됨.
exam.describe()
- 문자로 된 변수의 요약 통계량을 함께 출력하려면 describe()에 include = 'all'을 입력하면 됨
- 출력 결과를 보면 데이터를 구성하는 변수들의 요약 통계량을 알 수 있음.
- describe()를 실행해 출력되는 요약 통계량은 다음과 같은 의미를 가짐.
출력값 | 통계량 | 설명 |
count | 빈도(frequency) | 값의 개수 |
mean | 평균(mean) | 모든 값을 더해 값의 개수로 나눈 값 |
std | 표준편차(standard deviation) | 변수들의 값들이 평균에서 떨어진 정도를 나타낸 값 |
min | 최솟값(minimum) | 가장 작은 값 |
25% | 1사분위수(1st quantile) | 하위 25%(4분의 1) 지점에 위치한 값 |
50% | 중앙값(median) | 하위 50%(중앙) 지점에 위치한 값 |
75% | 3사분위수(3rd quantile) | 하위 75%(4분의 3) 지점에 위치한 값 |
max | 최댓값(maximum) | 가장 큰 값 |
- 출력 결과 중 math를 살펴보겠음.
- math는 학생들의 수학 시험 점수를 나타냄.
- 요약 통계량을 보면 다음과 같은 특징을 파악할 수 있음.
- 수학 시험 점수 평균은 57.45점(mean)
- 수학 시험 점수가 가장 낮은 학생은 20점(min), 가장 높은 학생은 90점(max)
- 학생들의 수학 점수가 54점(50%)을 중심으로 45.75점에서 75.75점 사이(25%, 75%)에 몰려있음.
[Do it! 실습] mpg 데이터 파악하기
이번에는 실제 데이터를 불러와 데이터의 특징을 파악해 보겠음. 먼저 mpg 데이터를 볼러오겠음. mpg(mile per gallon)는 미국 환경 보호국(US Environmental Protection Agency)에서 공개한 데이터로, 1999~2008년 미국에 출시된 자동차 234종의 정보를 담고 있음.
# mpg 데이터 불러오기
mpg = pd.read_csv('mpg.csv')
mpg 데이터 출처: bit.ly/easypy_51
1. head(), tail()을 이용해 데이터에 어떤 값이 담겨 있는 지 살펴보겠음.
mpg.head()
mpg.tail()
2. shape를 이용해 데이터가 몇 행, 몇 열로 구성되는지 알아보겠음.
mpg.shape
# output: (234, 11)
- 출력 결과를 보면 mpg는 234행, 11열로 구성되어 있음.
- 하나의 행이 자동차 한 종에 대한 정보를 의미하므로, mpg가 자동차 234종에 대한 11개 변수로 구성된다는 것을 알 수 있음.
3. info()를 이용해 변수의 속성을 알아보겠음.
mpg.info()
➊ 첫 번째~세 번째 행을 보면, mpg가 데이터 프레임이고 234행, 11개 변수로 구성된다는 것을 알 수 있음.
➋ Column 아래 manufacturer를 보면, 234개의 값이 있고 문자(object)로 된 변수라는 것을 알 수 있음. 그 밑으로도 같은 방식으로 각 변수의 속성을 보여줌. Dtype에서 object는 문자, float64는 소수점이 있는 실수, int64는 소수점이 없는 정수를 의미함.
{알아 두면 좋아요} mpg 데이터 살펴보기
앞으로 실습하면서 mpg 데이터를 자주 활용함. mpg 데이터의 변수들은 다음과 같은 속성을 의미함.
변수명 | 내용 | 변수명 | 내용 |
manufacturer | 제조 회사 | drv | 구동 방식(driver wheel) |
model | 자동자 모델명 | cty | 도시 연비(city) |
displ | 배기량(displacement) | hwy | 고속도로 연비(highway) |
year | 생산연도 | fl | 연료 종류(fuel) |
cyl | 실린더 개수(cylinders) | category | 자동차 종류 |
trans | 변속기 종류(transmission) | - | - |
4. describe()를 이용해 요약 통계량을 살펴보겠음.
mpg.describe()
- 출력 결과를 보면 mpg를 구성하는 변수 11개 중에서 숫자로 된 변수 5개의 요약 통계량만 출력되어 있음.
- 문자로 된 변수의 요약 통계량을 함께 출력하려면 describe()에 include = 'all'을 입력하면 됨.
mpg.describe(include = 'all')
- 문자 변수의 요약 통계량은 다음과 같은 의미를 담고 있음.
출력값 | 통계량 | 설명 |
count | 빈도 | 값의 개수 |
unique | 고유값 빈도 | 중복을 제거한 범주의 개수 |
top | 최빈값 | 개수가 가장 많은 값 |
freq | 최빈값 빈도 | 개수가 가장 많은 값의 개수 |
NaN은 결측치(누락된 값)을 의미함. unique, top, freq는 문자 변수로만 계산하므로 숫자 변수에는 NaN이 출력됨. 반대로 숫자를 이용해 계산하는 요약 통계량은 숫자 변수에만 출력되고 문자 변수에는 NaN이 출력됨.
➊ 숫자로 된 변수중 도시 연비를 의미하는 cty의 요약 통계량을 살펴보겠음. cty는 자동차가 도시에서 연료 1갤런에 몇 마일을 주행하는지 나타냄. 요약 통계량을 보면 다음 특징을 파악할 수 있음.
- 자동차가 도시에서 갤런당 평균 16.8마일 주행함(mean)
- 도시 연비가 가장 낮은 모델은 갤런당 9마일(min), 가장 높은 모델은 35마일(max) 주행함
- 도시 연비가 갤런당 17마일(50%)을 중심으로 14마일에서 19마일(25%, 75%) 사이에 몰려 있음.
➋ 문자로된 변수 중 자동차 제조 회사를 의미하는 manufacturer의 요약 통계량을 살펴보면 다음 특징을 파악할 수 있음.
- 자동차 제조 회사의 종류는 15개임(unique)
- 가장 많은 자동차 모델을 생산한 제조 회사는 dodge임(top)
- dodge는 37종의 모델을 생산함(freq)
- 지금까지 데이터 특징을 파악하는 함수를 알아봤음.
- 어떤 데이터를 분석하든 앞에서 익힌 함수를 활용해 전반적인 특징을 파악하는 작업을 가장 먼저 해야함.
[Do it! 실습] 함수와 메서드 차이 알아보기
함수는 종류에 따라 명령어를 입력하는 방법이 조금씩 다름. 함수를 사용하다 보면 익숙해지므로 따로 외울 필요는 없지만 입력 방법의 차이를 알아 두면 코드를 오류 없이 작성할 수 있음.
1. 내장 함수
- 내장 함수는 가장 기본적인 함수형태로, 함수 이름과 괄호를 입력하여 사용함.
- 파이썬에 내장되어 있으므로 별도로 패키지를 설치하거나 불러오지 않고 사용함.
sum(var)
max(var)
2. 패키지 함수
- 패키지 함수는 패키지 이름을 먼저 입력한 다음 점을 찍고 다음 점을 찍고 함수 이름과 괄호를 입력하여 사용함.
- 패키지 함수는 패키지를 로드해야 사용할 수 있음.
import pandas as pd
pd.read_csv('exam.csv')
pd.DataFrame({'x' : [1, 2, 3]})
3. 메서드
- 메서드(method)는 ‘변수가 지니고 있는 함수’임.
- 메서드는 변수명을 입력한 다음 점을 찍고 메서드 이름과 괄호를 입력하여 사용함.
pd.head()
pd.info()
- 메서드는 모든 변수에 사용할 수 있는 것이 아님. 변수의 자료 구조에 따라 사용할 수 있는 메서드가 다름. 예를 들어, head()는 데이터 프레임인 df에는 사용할 수 있지만, 리스트인 var에는 사용할 수 없음.
- 리스트는 17장에서 자세히 다룸.
pd.head()
pd.info()
var = [1, 2, 3]
var.head()
- 변수의 자료 구조는 type()을 이용하면 할 수 있음.
type(df)
# output: pandas.core.frame.DataFrame
type(var)
# output: list
[Do it! 실습] 어트리뷰드 알아보기
- 어트리뷰트(attribute)는 ‘변수가 지니고 있는 값’임.
- 어트리뷰트를 출력하려면 변수명 뒤에 점을 찍고 어트리뷰트 이름을 입력하면 됨.
- 어트리뷰트는 메서드와 마찬가지로 변수가 지니고 있으므로 변수명 뒤에 점을 찍고 입력함.
- 반면 메서드와 달리 괄호는 입력하지 않음.
- 괄호가 있으면 메서드, 없으면 어트리뷰트라고 생각하면 됨.
df.head()
# output: (...생략...)
df.shape
# output: (20, 5)
- 변수의 자료 구조에 따라 지니고 있는 어트리뷰트가 다름. 예를 들어 shape는 자료구조가 데이터 프레임인 변수가 지니고 있는 어트리뷰트임. 따라서 다음 코드의 출력 결과를 보면 자료 구조가 데이터 프레임인 df에는 사용할 수 있지만 리스트인 var에는 사용할 수 없음.
var.shape
메서드와 어트리뷰트의 차이
- 메서드와 어트리뷰트는 게임 캐릭터가 가지고 있는 기술과 능력치에 비유할 수 있음.
- 메서드 = 기술
메서드는 기사의 칼 휘두르기, 마법사의 불 쏘기처럼, 명령하면 실행하는 기술과 비슷함. 게임 캐릭터를 이용해 기술을 실행하듯 변수를 이용해 메서드를 실행함.
- 어트리뷰트 = 능력치
어트리뷰트는 체력, 공격력처럼 캐릭터의 능력치와 비슷함. 게임 캐릭터의 특징을 알고자 할 때 능력치라는 값을 살펴보듯 변수의 특징을 알고자 할 때 어트리뷰트라는 값을 출력하여 살펴봄.
05-2 변수명 바꾸기
데이터의 전반적인 특징을 파악하고 나면 본격적으로 분석하기 전에 변수명을 수정하는 작업을 해야 함. 변수명을 이해하기 쉬운 단어로 바꾸면 데이터를 수월하게 다룰 수 있음. 특히 변수명이 기억하기 어려운 문자로 되어 있으면 쉬운 단어로 바꾸는게 좋음. 예를 들어 9장에서 실습에서 사용하는 ‘한국복지패널 데이터’는 응답자의 성별이 h14_g3, 월급이 p1402_8aq1로 되어 있음. 이런 데이터는 변수명을 sex, income처럼 이해하기 쉽게 변경해야 헷갈리지 않고 분석할 수 있음.
[Do it! 실습] 변수명 바꾸기
- pandas의 df.rename()을 이용해 변수명을 바꾸는 방법을 알아보겠음.
1. 데이터 프레임 만들기
- 우선 실습에 활용하기 위해 변수 2개로 구성된 데이터 프레임을 만듦.
df_raw = pd.DataFrame({'var1': [1, 2, 1],
'var2': [2, 3, 2]})
df_raw
2. 데이터 프레임 복사본 만들기
- 변수명을 바꾸기 전에 원본을 보존하기 위해 데이터 프레임 복사본을 만듦.
- 새 변수명 df_new에 df_new.copy()를 할당하는 형태로 코드를 작성하면 됨.
- df.copy()는 데이터 프레임의 복사본을 만드는 기능을 함.
df_new = df_raw.copy() # 복사본 만들기
df_new # 출력
- 데이터를 변형하는 작업을 할 때는 원본을 직접 사용하기보다 복사본을 만들어 사용하는 습관을 들이는 게 좋음.
- 그래야 작업하다가 오류가 발생하더라도 원 상태로 되돌릴 수 있고, 데이터를 비교하면서 변형되는 과정을 검토할 수 있음.
3. 변수명 바꾸기
- 복사본을 만들었으니 df.rename()을 이용해 변수명을 바꾸겠음.
- df_new에 들어 있는 두 변수 var1, var2 중에서 var2를 v2로 바꾸겠음.
- df_new.rename()에 columns 파라미터를 추가한 다음 {'기존 변수명' : '새 변수명'}을 입력하면 됨. 출력 결과를 df_new에 할당하면 변수명이 바뀐 상태로 저장됨.
df_new = df_new.rename(columns = {'var2' : 'v2'}) # var2를 v2로 수정
df_new
- df.rename()은 pandas로 만든 데이터 프레임에 들어 있는 rename() 메서드를 의미함. 데이터 프레임의 메서드를 표현할 때 DataFrame.rename()처럼 풀어서 쓰기도 하고, DataFrame를 df로 줄여 df.rename으로 쓰기도 함.
- rename()에 입력한 {'var2' : 'v2'}는 딕셔너리 자료 구조임.
- 원본 df_raw와 복사본 df_new를 함께 출력하면 var2가 v2로 수정된 것을 비교해 볼 수 있음.
{알아 두면 좋아요} 데이터 프레임을 복사할 때 df.copy()를 사용하는 이유
데이터 프레임을 복사할 때 df_new = df_raw와 같이 코드를 작성할 수도 있음. 하지만 이렇게 하면 df_new와 df_raw는 이름만 다를 뿐 한 몸처럼 항상 같은 값을 갖게 되어 어느 한쪽을 수정하면 다른 한쪽도 수정됨.
데이터에 문제가 생겼을 때 원래대로 복구하기 위해 복사본을 만드는 것이므로 복사본을 수정해도 원본에 영향을 받지 않도록 df.copy를 사용해야 함.
{혼자해보기} mpg 데이터를 이용해 분석 문제를 해결해보세요.
- mpg 데이터의 변수명은 긴 단어를 짧게 줄인 축약어로 되어 있음.
- cty는 도시 연비, hwy는 고속도로 연비를 의미함. 변수명을 이해하기 쉬운 단어로 바꾸려고 함.
Q1. mpg 데이터를 불러와 복사본을 만드세요.
import pandas as pd
df_mpg = pd.read_csv('mpg.csv')
df_mpg_copy = df_mpg.copy()
Q2. 복사본 데이터를 이용해 cty를 city로, hwy를 highway로 수정하세요.
df_mpg_copy = df_mpg_copy.rename(columns = {'cty' : 'city',
'hwy' : 'highway'})
Q3. 데이터 일부를 출력해 변수명이 바뀌었는지 확인해보세요. 다음과 같은 결과물이 출력되어야 합니다.
df_mpg_copy
05-3 파생변수 만들기
데이터에 들어 있는 변수만 이용해 분석할 수도 있지만, 변수를 조합하거나 함수를 이용해 새 변수를 만들어 분석할 수도 있음. 예를 들어 여러 과목의 시험 점수를 조합해 전과목 평균 변수를 만들어 분석할 수 있음. 이처럼 기존의 변수를 변형해 만든 변수를 파생변수(derived variable)라고 함.
[Do it! 실습] 변수를 조합해 파생변수 만들기
데이터 프레임의 변수를 조합해 파생변수를 만드는 방법을 알아보겠음.
1. 실습에 활용하기 위해 변수 2개로 구성된 데이터 프레임을 만듦.
df = pd.DataFrame({'var1': [4, 3, 8],
'var2': [2, 6, 1]})
df
2. var1과 var2 변수의 값을 더한 var_sum이라는 파생변수를 만들어 df에 추가해 보겠음. 데이터 프레임명에 []를 붙여 새로 만들 변수명을 입력하고 =로 계산 공식을 할당하는 형태로 코드를 작성하면 됨. 새로 만든 변수는 데이터 프레임의 오른쪽 끝에 나열됨.
df['var_sum'] = df['var1'] + df['var2'] # var_sum 파생변수 만들기
df
3. 이번에는 var1과 var2를 더한 다음 2로 나눠 var_mean이라는 파생변수를 만들어 보겠음.
df['var_mean'] = (df['var1'] + df['var2']) / 2 # var_mean 파생변수 만들기
df
[Do it! 실습] mpg 통합 연비 변수 만들기
이번에는 mpg 데이터를 이용해 파생변수를 만들어 보겠음. mpg 데이터에는 도시 연비를 의미하는 cty, 고속도로 연비를 의미하는 hwy, 두 종류의 연비 변수가 있음. 이 변수들을 이용하면 도로 유형별로 각각 분석할 수 있지만, 도로 유형을 통틀어 어떤 자동차 모델의 연비가 높은지는 분석할 수 없음. 그러므로 종합해서 분석하려면 하나로 통합된 연비 변수가 필요함. 앞에서 익힌 방법을 활용해 통합 연비 변수를 추가해 보겠음.
1. cty, hwy 두 변수를 더해 2로 나눠 도로 유형을 통합한 연비 변수를 만듦. 데이터 일부를 출력하면 변수가 추가된 것을 확인할 수 있음.
mpg['total'] = (mpg['cty'] + mpg['hwy']) / 2 # 통합 연비 변수 만들기
mpg.head()
2. 변수를 추가하고 나면 분석하는 데 활용할 수 있음. 통합 연비 변수의 평균을 구해보겠음.
sum(mpg['total']) / len(mpg) # total 합계를 행 수로 나누기
# output: 20.14957264957265
- sum()과 len() 대신 df.mean() 메서드를 이용하면 평균을 간단히 구할 수 있음.
mpg['total'].mean() # 통합 연비 변수 평균
# output: 20.14957264957265
[Do it! 실습] 조건문을 활용해 파생변수 만들기
변수를 조합하는 방법 외에도 함수를 이용해서 파생변수를 만들 수 있음. 이번에는 조건에 따라 서로 다른 값을 반환하는 서로 다른 값을 반환하는 ‘조건문 함수’로 파생변수를 만드는 방법을 알아보겠음. 전체 자동차 중에서 연비 기준을 충족해 ‘고연비 합격 판정’을 받은 자동차가 몇 대나 되는지 알아보는 상황을 가정해 보겠음. 연비가 기준값을 넘으면 합격, 넘지 못하면 불합격을 부여하도록 변수를 만들면 문제를 해결할 수 있음.
1. 기준값 정하기
- 먼저 몇을 기준으로 합격 여부를 판단할지 정해야 함.
- 변수의 요약 통계량을 출력하는 describe()를 이용해 앞에서 만든 통합 연비 변수 total의 평균(mean)과 중앙값(50%)을 확인함.
mpg['total'].describe() # 요약 통계량 출력
- 이번에는 히스토그램을 만들어 자동차들의 연비 분포를 알아보겠음.
- 히스토그램은 빈도를 막대 길이로 표현한 그래프임.
- 히스토그램을 보면 어떤 값이 지닌 데이터가 많은지 전반적인 분포를 알 수 있음.
- df.plot.hist()를 이용하면 히스토그램을 만들 수 있음.
# 그래프 만들기
mpg['total'].plot.hist()
- 히스토그램을 보면 x축에는 5 간격으로 total 변수의 값이 표현되어 있고, y축에는 각 계급 구간의 빈도(Frequency)가 표현되어 있음. 요약 통계량과 히스토그램을 보면 다음 사실을 알 수 있음
- total 연비의 평균과 중앙값은 약 20
- total 연비가 20~22.5 사이인 자동차 모델이 가장 많음.
- total 연비는 대부분 25 이하이고, 25를 넘기는 모델은 많지 않음.
- 요약 통계량과 히스토그램을 종합하면 연비가 20이 넘는 자동차에 고연비 합격 판정을 내리면 적당할 것으로 판단됨.
- 기준값을 정했으니 total 변수가 20을 넘으면 합격, 넘지 못하면 불합격으로 분류한 변수를 만들겠음.
2. 합격 판정 변수 만들기
- 조건에 따라 서로 다른 값을 반환하는 함수를 ‘조건문(conditional statements) 함수’라고 함.
- 조건문 함수를 이용하면 특정 조건을 만족했는지 여부에 따라 서로 다른 값을 부여해 변수를 만들 수 있음.
- Numpy 패키지의 where()를 이용하면 조건에 따라 서로 다른 값을 부여할 수 있음.
- 우선 Numpy를 사용할 수 있도록 로드하겠음.
- Numpy는 배열 연산, 통계치 연산 등 수치 연산을 할 때 자주 사용하는 패키지임.
import numpy as np
- np.where()는 지정한 조건에 맞을 때와 맞지 않을 때 서로 다른 값을 반환하는 기능을 함. 괄호 안에 ➊조건, ➋조건에 맞을 때 부여할 값, ➌조건에 맞지 않을 때 부여할 값 순서로 코드를 작성하면 됨.
다음 코드를 실행하면 total이 20 이상이면 ‘pass’를 부여하고 그렇지 않으면 ‘fail’을 부여해 test라는 변수를 만듦. mpg를 출력하면 total 변수의 오른쪽에 test 변수가 위치하고, 20을 기준으로 ‘pass’ 또는 ‘fail’이 부여된 것을 확인할 수 있음.
# 20 이상이면 pass, 그렇지 않으면 fail 부여
mpg['test'] = np.where(mpg['total'] > 20, 'pass', 'fail')
mpg.head()
- 기준값을 넘으면 합격, 넘지 못하면 불합격을 부여한 변수를 만들었으니 이제 합격 판정을 받은 자동차와 불합격 판정을 받은 자동차가 각각 몇 대인지 알아볼 차례임.
3. 빈도표로 합격 판정 자동차 수 살펴보기
- 빈도표(frequency table)는 변수의 값이 종류별로 몇 개씩 있는지, 값의 개수를 나타낸 표임.
- df.value_counts()를 이용해 빈도표를 만들면 합격한 자동차와 불합격한 자동차가 각각 몇 대인지 알 수 있음.
mpg['test'].value_counts() # 연비 합격 빈도표 만들기
- 출력 결과를 보면 합격 판정을 받은 자동차는 128대, 불합격한 106대라는 것을 알 수 있음.
4. 막대 그래프로 빈도 표현하기
- 막대 그래프를 만들면 변수의 값이 종류별로 얼마나 많은 지 한눈에 파악할 수 있음.
- 도표로 변수를 만든 다음 막대 그래프를 만드는데 활용하겠음.
count_test = mpg['test'].value_counts() # 연비 합격 빈도표를 변수에 할당
count_test.plot.bar() # 연비 합격 빈도 막대 그래프 만들기
축 이름 회전하기
- 앞에서 출력한 그래프를 보면 축 이름이 회전되어 있음.
- df.plot.bar()의 기본값이 축 이름을 90도 회전하게 되어있기 때문임.
- rot 파라미터에 숫자를 입력하면 축 이름을 원하는 각도만큼 회전할 수 있음.
- 축 이름을 수평으로 만들려면 rot = 0을 입력하면 됨.
count_test.plot.bar(rot = 0) # 축 이름 수평으로 만들기
[Do it! 실습] 중첩 조건문 활용하기
등급 | 기준 |
A | 30 이상 |
B | 20~29 |
C | 20 미만 |
앞에서는 자동차 모델을 합격과 불합격 둘 중 하나로 분류한 변수로 만들었음. 이번에는 A, B, C 세 종류의 연비 등급으로 분류한 변수를 만들어 보겠음. total이 30 이상이면 A, 20~29는 B, 20 미만이면 C 등급으로 분류하겠음.
범주 값을 3가지 이산으로 부여하려면 np.where() 안에 다시 np.where()를 넣는 형식으로 조건문을 중첩해 작성해야함. 조건문을 여러개 중첩한 코드를 ‘중첩 조건문’이라고 함.
1. 연비 등급 변수 만들기
다음은 연비에 따라 3가지 등급을 부여해 grade 변수를 만드는 코드임. np.where() 안에 또 다른 np.where()가 들어 있는 형태로 구성되어 있음. 출력 결과를 보면 test 변수 오른쪽에 total 변수의 값을 기준으로 만든 grade 변수를 확인할 수 있음
# total 기준으로 A, B, C 등급 부여하기
mpg['grade'] = np.where(mpg['total'] >= 30, 'A',
np.where(mpg['total'] >= 20, 'B', 'C'))
# 데이터 확인
mpg.head()
- 이 코드는 다음 순서로 진행됨.
- 첫 번째 np.where()의 조건에 따라 total이 30 이상이면 ‘A’를 부여함.
- 조건에 맞지 않으면 두 번째 np.where()를 실행함. 두 번째 조건에 따라 total이 20 이상이면 ‘B’를 부여함.
- 두 번째 조건도 맞지 않으면 ‘C’를 부여함.
2. 빈도표와 막대 그래프로 연비 등급 살펴보기
- 연비 등급 변수를 만들었으니 빈도표와 막대 그래프를 만들어 등급별 빈도를 확인하겠음.
count_grade = mpg['grade'].value_counts() # 등급 빈도표를 변수에 할당
count_grade
count_grade.plot.bar(rot = 0) # 등급 빈도 막대 그래프 만들기
- 출력된 빈도표와 막대 그래프를 보면 연비 등급이 B, C, A 순으로 많다는 것을 알 수 있음.
알파벳 순으로 막대 정렬하기
- 앞에서 출력한 그래프는 막대가 B, C, A 순으로 정렬되어 있음.
- 이는 그래프를 만드는데 사용한 count_grade가 빈도 기준으로 내림차순 정렬되어 있기 때문임.
- 빈도표를 알파벳순으로 정렬한 다음 그래프를 만들면 막대가 알파벳순으로 정렬됨. 빈도표를 알파벳순으로 정렬하려면 df.value_counts()에 sort_index()를 추가하면 됨.
# 등급 빈도표 알파벳순 정렬
count_grade = mpg['grade'].value_counts().sort_index()
count_grade
- 이제 count_grade로 그래프를 만들면 막대가 알파벳순으로 정렬됨.
# 등급 빈도 막대 그래프 만들기
count_grade.plot.bar(rot = 0)
{알아두면 좋아요}
메서드 체이닝
mpg['grade'].value_counts().sort_index()와 같이 점(.)을 이용해 메서드를 계속 이어서 작성하는 방법을 메서드 체이닝(method chaining)이라고 함. 메서드 체이닝을 이용하면 변수에 여러 메서드를 순서대로 적용할 수 있으므로 출력 결과를 변수에 할당하고 다시 불러오는 작업을 반복하지 않아도 됨. 다음 두 코드는 결과가 같음.
# 출력 결과를 변수에 할당하는 방법
df = mpg['grade']
df = df.value_counts()
df = df.sort_index()
# 메서드 체이닝
df = mpg['grade'].value_counts().sort_index()
필요한 만큼 범주 만들기
- 앞에서는 np.where()를 두 번 중첩해 세 범주로 구성된 변수를 만들었음.
- np.where()를 한 번 더 중첩하면 원하는 만큼 범주의 수를 늘릴 수 있음.
- ‘범주의 수-1’만큼 np.where()를 중첩하면 됨.
- 다음은 np.where()를 세 번 중첩해 네 범주의 등급 변수를 만드는 코드임.
- np.where()를 3번 반복하므로 여는 괄호와 닫는 괄호가 각각 3개임.
- 코드 마지막에 닫는 괄호를 3개 입력해야함.
- 마찾가지로 쉼표도 np.where()마다 2개씩, 총 6개임.
# A, B, C, D 등급 변수 만들기
mpg['grade2'] = np.where(mpg['total'] >= 30, 'A',
np.where(mpg['total'] >= 25, 'B',
np.where(mpg['total'] >= 20, 'C', 'D')))
{ Tip } 이 코드는 두 번째, 세 번째 np.where()를 [Enter]로 줄을 바꾼 다음 열을 맞추어 작성했음. 이렇게 줄을 바꾸면 한 줄로 작성할 때보다 코드의 전체 구조가 눈에 더 잘 들어옴. 코드가 길어질 때 줄을 바꾸는 습관을 들이면 코드를 가독성 있게 작성할 수 있음.
[Do it! 실습] 목록에 해당하는행으로 변수 만들기
- 여러 조건 중 하나에 해당하면 특정 값을 부여해 파생변수를 만들 때가 있음. 예를 들어 mpg 데이터의 category가 ‘compact’, ‘subcompact’, ‘2seater’면 ‘small’을 부여하고 그렇지 않으면 ‘large’를 부여한 파생변수를 만드는 것임. 이럴 때는 ‘또는(or)’을 의미하는 | 기호를 이용해 여러 조건을 나열하면 됨. |는 키보드의 [Backspace] 밑에 있는 [ \ ]를 [Shift]와 함께 누르면 됨.
- np.where()에 여러 조건을 입력할 때는 각 조건을 괄호에 입력해야 하니 주의하기.
( Tip ) | 기호는 ‘버티컬 바(vertival bar)’라고 읽음
|와 ,뒤에서 를 입력해 줄을 바꾸면 코드의 가독성을 높일 수 있음.
mpg['size'] = np.where((mpg['category'] == 'compact') |
(mpg['category'] == 'subcompact') |
(mpg['category'] == '2seater'),
'small', 'large')
mpg['size'].value_counts()
앞의 코드는 np.where()에 ‘또는’ 조건이 여러 번 반복됨. 이럴 때 df.isin()을 사용하면 코드를 간편하게 작성할 수 있음. df.isin()에 []를 이용해 조건 목록을 입력하면 됨. df.isin()은 변수의 값이 입력한 목록에 해당하는지 확인하는 기능을 함. 다음 코드는 앞의 코드와 결과가 같음.
mpg['size'] = np.where(mpg['category'].isin([
'compact', 'subcompact', '2seater']),
'small', 'large')
mpg['size'].value_counts()
정리하기
# 1. 패키지 로드하기
import pandas as pd
import numpy as np
# 2. 데이터 불러오기
mpg = pd.read_csv('mpg.csv')
# 3. 데이터 파악하기
mpg.head() # 데이터 앞부분
mpg.tail() # 데이터 뒷부분
mpg.shape # 행, 열 수
mpg.info() # 속성
mpg.describe() # 요약 통계량
# 4. 변수명 바꾸기
mpg = mpg.rename(columns = {'manufactuer' : 'company'})
# 5. 파생변수 만들기
mpg['total'] = (mpg['cty'] + mpg['hwy']) / 2 # 변수 조합
mpg['test'] = np.where(mpg['total'] >=20, 'pass', 'fail') # 조건문 활용
# 6. 빈도 확인하기
count_test = mpg['test'].value_counts() # 빈도표 만들기
count_test.plot.bar(rot = 0) # 빈도 막대 그래프 만들기
분석 도전
midwest.csv는 미국 동북중부(East North Central States) 437개 지역의 인구통계 정보를 담고 있음. midwest.csv를 이용해 데이터 분석 문제를 해결해 보세요.
문제1) midwest.csv를 불러와 데이터의 특징을 파악하세요.
# 패키지 로드하기
import pandas as pd
import numpy as np
# 데이터 불러오기
df = pd.read_csv('midwest.csv')
df_copy = df.copy()
# 데이터 파악하기
df_copy.head()

df_copy.tail()

df_copy.shape
# output: (437, 28)
df_copy.info()

df_copy.describe(include='all')


- midwest.csv는 437개의 행과 11개의 열로 구성됨.
- 미국 동북중부에 있는 지역은 평균적으로 전체인구가 9.613030e+04 명이 살고 있음(mean).
- 가장 인구가 적은 지역은 1.701000e+03명이 살고 있고(min), 가장 인구가 많은 지역은 5.105067e+06 명이 살고 있음(max).
- 미국 동북중부에 있는 지역별 전체인구는 3.532400e+04 명(50%)을 중심으로 1.884000e+04 명에서 7.565100e+04 명(25%, 75%) 사이로 몰려 있음.
문제2) poptotal(전체 인구) 변수를 total로, popasian(아시아 인구) 변수를 asian으로 수정하세요.
# 변수명 바꾸기
df_copy = df_copy.rename(columns = {'poptotal' : 'total',
'popasian':'asian'})
df_copy.head

문제3) total, asian 변수를 이용해 ‘전체 인구 대비 아시아 인구 백분율’ 파생 변수를 추가하고 히스토그램을 만들어 분포를 살펴보세요.
# 파생변수 추가
df_copy['asian_rate'] = (df_copy['asian'] / df_copy['total']) * 100
# 히스토그램 만들기
df_copy['asian_rate'].plot.hist()

- 히스토그램을 보면 x축에는 0.5 간격으로 asian_rate(미국 동북중부 지역의 전체인구 대비 아시아 인구) 변수의 값이 표현되어 있고, y축에는 각 구간의 빈도(Frequency)가 표현되어 있음. 요약 통계량과 히스토그램을 보면 다음 사실을 알 수 있음
- asian_rate는 평균적으로 49%에 해당함.
- asian_rate는 대부분 30% 이하이고, 52%를 넘기는 지역은 많지 않음.
문제4) 아시아 인구 백분율 전체 평균을 구하고, 평균을 초과하면 ‘large’, 그 외에는 ‘small’을 부여한 파생변수를 만들어 보세요.
# 아시아 인구 백분율 전체 평균
asian_rate_mean = df_copy['asian_rate'].mean()
asian_rate_mean
# output: 0.48724618343573406
asian_rate_mean(아시아 인구 백분율 전체 평균)은 약 0.49이므로, 0.49을 기준으로 초과하면 ‘large’, 그 외에는 ‘small’을 부여하겠음.
# 파생변수 만들기
df_copy['asian_rate_size'] = np.where(df_copy['asian_rate'] > 0.49,
'large', 'small')
df_copy.describe(include='all')

문제5) ‘large’와 ‘small’에 해당하는 지역이 얼마나 많은지 빈도표와 빈도 막대 그래프를 만들어 확인해 보세요.
# 빈도표 만들기
count_asian = df_copy['asian_rate_size'].value_counts()
count_asian

# 빈도 막대 그래프 만들기
count_asian.plot.bar(rot = 0)

- 5장 END -
'데이터 분석(Data Analysis) > 쉽게 배우는 파이썬 데이터 분석' 카테고리의 다른 글
[둘째마당_본격실습! 데이터 갖고 놀기] 07 데이터 정제 - 빠진 데이터, 이상한 데이터 제거하기 (0) | 2023.12.23 |
---|---|
[둘째마당_본격실습! 데이터 갖고 놀기] 06 자유자재로 데이터 가공하기 (0) | 2023.12.18 |
[둘째마당_본격실습! 데이터 갖고 놀기] 04 데이터 프레임의 세계로 (0) | 2023.12.16 |
[첫째마당_파이썬이랑 친해지기] 03 데이터 분석에 필요한 연장 챙기기 (0) | 2023.12.15 |
[첫째마당_파이썬이랑 친해지기] 01 안녕, 파이썬? (0) | 2023.12.14 |