본문 바로가기

About 배우고 익히는법/Python

Pandas dataframe - 판다스 데이터프레임 활용 기초 [출처] [파이썬 데이터 분석] Pandas dataframe - 판다스 데이터프레임 활용 기초

오늘 사용할 데이터는 공공데이터포털(https://www.data.go.kr/)에서 다운로드한 "2016년 교통사고 데이터"입니다. 사망 교통사고 관련 사고유형, 발생일시, 피해자 수, 피해자 유형 등 다양한 항목에 대한 데이터입니다. 아래 파일을 다운로드하여 참고하시기 바랍니다.  

2016년 도로교통공단_전국_사망교통사고 통계 데이터 
(출처: 공공데이터포털)


Pandas 라이브러리 불러 오기

import 명령을 사용하여 판단스 라이브러리를 pd라는 네임스페이스를 사용하여 불러 옵니다. (네임스페이스는 명령어를 간단하게 축약하여 사용하기 위한 개념입니다. pandas라고 full name을 입력할 필요가 없고, pd라는 약칭을 사용할 수 있게 됩니다.)

import pandas as pd

자료 파일(file)을 dataframe으로 읽어 오기
CSV file data를 읽어 오기 위하여, pandas.read_csv() 함수를 사용합니다.  file_path에 파이썬(.py)파일이 있는 폴더(./)에 저장되어 있는 'traffic_accident_2016.csv' 파일을 지정하고, pandas.read_csv() 함수의 인자로 전달합니다. 읽어 들인 결과를 df라는 변수에 저장합니다. (이 때, pandas가 csv 파일을 dataframe으로 변환합니다.)(
 
file_path="./traffic_accident_2016.csv" 
df = pd.read_csv(file_path)


데이터가 dataframe으로 잘 변환되었는지 확인해 봅니다. 이 때 여러 가지 기본적인 함수(method)를 사용 가능합니다. 먼저 자료의 첫 줄부터 n개의 행을 지정하여 보고 싶을 때는 .head(n) 함수를, 마지막 n 개의 행을 지정하여 보고 싶을 때는 .tail(n) 메소드를 사용 가능합니다. 

# 처음 5 rows, 10 rows 출력
df.head(5)
df.head(10)


# 마지막 5 rows, 10 rows 출력
df.tail(5)
df.tail(10)


*** df.head(5) 출력 결과

pandas.head()


*** df.head(10) 출력 결과

pandas.head()


*** df.tail(5) 출력 결과

pandas.tail()


자료 구조 파악하기
데이터프레임 자료구조를 설명하는 함수들이 있습니다. 대표적으로 .info()와 .describe()가 있습니다. 데이터 값의 타입을 보여주고, 자료값의 대표적인 통계값을 요약해서 출력해 주기 때문에, 데이터의 전반적인 구성과 형태를 파악하는데 아주 유용합니다. 

df.info()

df.info()

df.info() 출력 결과를 보면, df라는 변수에 저장된 자료 구조의 pandas dataframe이라는 것을 알 수 있습니다. index는 숫자 범위(0~4118)이므로, 총 4119개의 사고 데이터를 담고 있음을 알 수 있네요. column은 27개이고 사고 발생시점, 사상자수, 발생지역, 사고유형 등 정보로 구분됩니다. 각 column별 데이터 갯수와 타입을 확인 가능합니다.


df.describe()

df.describe() 출력 결과에서는 숫자 데이터(Numeric Data)를 가지고 있는 column별 데이터 겟수, 평균, 표준편차, 최소값, 최대값 등의 통계값을 요약해서 보여주고 있습니다. 데이터 분포를 간단하게 살펴볼 수 있겠네요. 

또한, 아래와 같이 column 명칭과 index 명칭을 별도로 확인하는 함수 메소드도 있습니다. 


# column 명칭 확인
df.columns.values

# index 명칭 확인
df.index.values


불필요한 컬럼(column) 삭제하기
소스 데이터를 살펴 보면, 불필요한 자료도 있고 일부 보완이 필요한 자료값들도 존재합니다. 판다스 pandas 라이브러리는 이런 과정을 매우 빠르고 쉽게 할 수 있습니다.  

먼저, 불필요하다고 생각하는 몇 개의 column을 .drop( ) 함수를 사용하여 삭제하겠습니다. 함수 인자로 [column 명칭]으로 구성되는 리스트를 전달하고, 삭제가 이루어지는 축방향(axis)를 1로 설정합니다. inplace 옵션을 True로 지정해야만, df라는 변수가 가리키는 원본 데이터프레임이 수정됩니다. 

df.drop(['발생년', '발생분', '사고유형', '법규위반_대분류', '발생위치X_UTMK', '발생위치Y_UTMK'], axis=1, inplace=True)

# column 명칭 재확인
df.columns.values

df.drop() 컬럼 삭제


열(column) 이름 변경
컬럼 명칭이 너무 길어서 줄이고 싶거나, 의미를 명확하게 하기 위해서 column 이름을 바꾸고 싶을 때가 있습니다. 이럴 때는 .rename( ) 함수 메소드를 이용하면 가능합니다. 함수 인자로 columns={변경전 명칭:변경후 명칭}과 같이 dictionary  타입으로 만들어서 지정합니다. inplace 옵션을 True로 지정하는 것도 잊지 마시길 바랍니다.  


df.rename(columns={'발생년월일시':'월일시', 
                   '사망자수':'사망', '사상자수':'사상', '중상자수':'중상', 
                   '경상자수':'경상', '부상신고자수':'부상', 
                   '발생지시도':'시도', '발생지시군구':'시군구', 
                   '사고유형_대분류':'유형A', '사고유형_중분류':'유형B',
                   '도로형태_대분류':'도로A', '도로형태':'도로B',
                   '당사자종별_1당_대분류':'가해A', '당사자종별_1당':'가해B',
                   '당사자종별_2당_대분류':'피해A', '당사자종별_2당':'피해B',
                   '법규위반':'법규' }, inplace=True)

# column 명칭 재확인
df.columns.values

df.rename( ) 컬럼 이름 변경


신규 열(column) 추가
이번에는 기존 데이터프레임에 새로운 열(column)을 추가하겠습니다. 숫자(int64) 타입으로 저장되어 있는 월일시 데이터를 .astype 메소드를 이용하여 문자열(string)로 변환하여 주고, 문자열 슬라이싱(slicing)을 사용하여 월, 일, 시를 구분하여 각각 새로운 열(column)으로 만들어서 추가합니다. 그리고, 이제 사용하지 않을 '월일시' 열을 삭제합니다. 

#월일시를 월, 일, 시로 구분
df['월'] = df['월일시'].astype(str).str[4:6]
df['일'] = df['월일시'].astype(str).str[6:8]
df['시'] = df['월일시'].astype(str).str[8:]

# '월일시' column을 삭제
df.drop(['월일시'], axis=1, inplace=True)

# 처음 5 rows 출력
df.head(5)

신규 열(column) 추가, 삭제


자료가 없는 데이터(missing value) 확인하기
이번에는 자료값이 없는 데이터를 확인해서 삭제하는 방법을 알아보고, 데이터 고유값을 확인하고 갯수를 세어 보는 작업까지 해보겠습니다.  


# .isnull( ) 함수: 값이 없는 데이터(missing value)의 유무를 True, False로 반환
missing_df = df.isnull()
missing_피해유형 = df[['피해A', '피해B']].isnull()

.isnull() - 자료가 없는 데이터(missing value) 확인하기

.isnull() 메소드는 missing data가 있는 경우에 True를 반환하고 없는 경우에는 False를 반환하는데, 처음 5 rows에는 missing data가 없는 것으로 확인됩니다. missing_피해유형 dataframe의 데이터 분포를  .describe() 메소드를 사용하여 확인합니다. 

4119개의 데이터 중에서 unique한 고유값은 2개(당연히 True와 False가 되겠죠)입니다. 그 중에서 False값이 가장 많고, 그 갯수는 3294개입니다. 따라서, 상당히 많은 missing value가 있는 것을 알 수 있습니다. 

# 데이터 값 분포를 확인
missing_피해유형.describe()

.describe()


데이터를 잘 살펴보면, 피해A, 피해B 열(column)에 값이 없는 경우는 차량 운전자 단독으로 발생한 사고로써 사고 상대방이 없는 경우입니다. 차량 1대가 혼자서 사고 낸 경우를 말하는 것이므로, 이 경우만 따로 삭제하고 그 결과를 new_df라는 변수에 새로운 dataframe으로 저장합니다. new_df 데이터프레임의 고유값을 확인해 봅니다. 

# 값이 없는 데이터(missing value)를 피해A, 피해B column에서 찾아서, 그 열을 삭제
new_df = df.dropna(subset=['피해A', '피해B'], axis=0)
# new_df 구조 확인
new_df.head(5)

.dropna( ) - missing value 삭제


# 데이터 값을 중복 없이 unique한 값의 배열로 출력 (데이터 고유값)
new_df['피해A'].unique()

.unique()


# 데이터 고유값(피해자 유형) 별로 데이터 갯수 계산
new_df['피해A'].value_counts()

.value_counts()


# 가장 갯수가 많은 데이터 고유값(피해자 유형)을 출력
new_df['피해A'].value_counts().idxmax()

.value_counts().idxmax()



마지막으로 
작업한 결과를 새로운 파일로 저장하고 마무리합니다.