파이썬 기초 05 Pandas and DataFrame

파이썬 기초 05 Pandas and DataFrame

preface 이번 포스트에서는 파이썬을 이용하여 데이터분석의 핵심이라 할 수 있는 pandas 패키지에 대해 알아보겠습니다. pandas 패키지는 숫자와 문자를 함께 표현한 테이블인 dataframe 을 사용할 수 있게 하여 R 혹은 SAS 와 유사하다는 인상을 받았습니다.

다음 자료를 참고하였습니다:

Import Data 외부 데이터 읽어오기

주의

import pandas as pd
import numpy as np

# TXT data, 구분자: comma
info = pd.read_csv("d:/info.txt",sep=",",encoding="euc-kr") # default는 UTF-8
info

# CSV : Comma Separated Value
population = pd.read_csv("d:/population.csv",sep=",",encoding="euc-kr") # default는 UTF-8
population

# 엑셀
apart = pd.read_excel("d:/apart.xls",sheetname=0)
apart

# 데이터 일부 보기 : 데이터명.head(), 데이터명.tail()
# 모든 데이터를 불러오면 너무 많으니 일부만 불러와서 확인합니다.
apart.head(10)

데이터 살펴보기


apart.index   # RangeIndex(start=0, stop=763, step=1)
apart.shape   # (763, 14)
apart.columns # Index(['ID', '시군구', '읍면동', '본번', '부번', '단지명', '전월세구분', '전용면적', '계약일', '보증금(만원)', '월세(만원)', '층', '건축년도', '도로명'], dtype='object')

# 특정한 변수의 데이터 가져오기
apart["전용면적"]
apart.전용면적
apart.전용면적.head(10)
apart[["전용면적","전월세구분"]].head()

# 중복된 자료를 제외한 목록: numpy의 unique() 함수 사용
np.unique(apart["전월세구분"])

# 전월세구분에 대한 빈도(frequency): 데이터명["변수명"].value_counts()
apart["전월세구분"].value_counts()
apart["전월세구분"].value_counts().sort_values() # 빈도의 결과를 오름차순으로 정렬
apart["전월세구분"].value_counts().sort_values(ascending=False) # 빈도의 결과를 내림차순으로 정렬

Descriptive Statistics with Pandas 기술통계량

# 데이터 중에서 양적 자료에 대한 기술통계량: 데이터명.describe()
apart.describe()

# 특정 자료에 대한 기술통계량: 데이터명["변수명"].describe()
apart["전용면적"].describe()
apart["전용면적"].mean()
apart["전용면적"].std()

Graphs 그래프 그리기

참고: python 과 그래프

import matplotlib.pyplot as plt

# 막대그래프
rental_freq = apart["전월세구분"].value_counts()
rental_freq.plot(kind="bar")
plt.show()

#가로막대그래프
rental_freq.plot(kind="barh")
plt.show()


# 일변량(Univariate) 양적 자료에 대한 그래프

# 히스토그램(Histogram): 데이터명["변수명"].hist()
apart["전용면적"].hist()
plt.show()

apart["전용면적"].hist(bins=[0,50,100,150,200,250]) # 구간 지정
plt.show

apart["전용면적"].hist(bins=50) #구간의 갯수를 50개로
plt.show()


# 상자그림(Boxplot): 양적 자료에 이상치(Outlier)가 있는지 알려주는 그래프
apart.boxplot(column="전용면적")
plt.show()

apart.boxplot(column="전용면적", by="전월세구분") # 집단별 상자그림(Boxplot) - 집단은 기본적으로 질적 자료
plt.show()

만약 jupyter notebook 을 이용하여 코딩한다면, %matplotlib inline 를 끼워넣으면 매번 plot.show() 를 하지 않아도 됩니다.

DataFrame Merge 데이터프레임 합치기

d1=pd.DataFrame({"id":[1,2,3],"bt":["A","B","B"]})
d2=pd.DataFrame({"id":[4,5],"bt":["O","O"]})
d3=pd.DataFrame({"id":[1,2,4,5],"age":[10,20,40,50]})


# 데이터 위/아래로 합치기:concat - 데이터의 모습이 같아야 함
pd.concat([d1,d2])

# 데이터 오른쪽/왼쪽으로 합치기: merge - 동일한 key 값이 있어야 함
pd.merge(d1,d3,on="id")              # inner join (default)
pd.merge(d1,d3,on="id", how="outer") # outer join
pd.merge(d1,d3,on="id", how="left")  # left join
pd.merge(d1,d3,on="id", how="right") # right join

DataFrame Indexing and Subsetting 데이터프레임 인덱싱 이해하기

import numpy as np
import pandas as pd

data = {"names":["Kilho", "Kilho", "Charles", "Charles"],
        "year":[2014, 2015, 2015, 2016],
        "points":[1.5, 1.7, 2.4, 2.9]}

df = pd.DataFrame(data,
                  columns=["year", "names", "points", "panalty"],
                  index=["one", "two", "three", "four"])

# year 행만 따로 부르기
df["year"]
df.year

# year, points 두 개의 행만 따로 부르기
df[["year", "points"]]

# palaty 라는 행을 추가로 만들고 값을 입력
df["palaty"] = 0.5
df["palaty"] = [0.1, 0.2, 0.3, 0.4]

# 0 ~ 4 까지 숫자 입력
df["panalty"] = np.arange(4)

# column 끼리 계산
df["net_points"] = df["points"] - df["panalty"]

# 행 삭제하기
del df["palaty"]
del df["net_points"]
df.columns # Index(['year', 'names', 'points', 'panalty'], dtype='object')


# Subsetting
df[0:3]
df["two":"four"]
df.loc["two":"four", "points"] # .loc 는 인덱스 명칭에 기반한 subset function

df.loc[: , ["year", "points"]]

df.loc["six", :] = [2013, "HOng", 4.0, 0.2]

df.iloc[0:2, 1:3] # .iloc 는 인덱스 번호에 기반한 subsetting function

# Subsetting by Conditions
df.loc[df["year"] > 2014]
df.loc[df["names"] == "Kilho", ["names", "points"]]
df.loc[(df["points"] > 2) & (df["points"] < 4), :]

DataFrame Control 데이터프레임 조작하기

import numpy as np
import pandas as pd

df = pd.DataFrame(np.random.randn(6, 4))

# columns / rows 에 인덱스 붙이기
df.columns = ["A", "B", "C", "D"]
df.index = pd.date_range("20170401", periods=6) # 0 ~ 5 로 붙어있던 인덱스 대신 2017-04-01 ~ 2017-04-06 으로 변경

# E column 을 새로 만들어서 아래와 같은 값을 할당
df["E"] = [1.0, np.nan, 3.5, 6.1, np.nan, 7.0]

# NaN 값 처리: 삭제
df.dropna(how="any") # 해당 row 에서 하나라도 NaN 이 있으면 row 삭제
df.dropna(how="all") # 해당 row 에서 모두 NaN 인 경우 row 삭제

# NaN 값 처리: 특정 값 입력
df.fillna(value=0.5)

# 비어있는(null) 값 찾기
df.isnull()
df.loc[df.isnull()["E"], :] # E column에서 비어있는 값을 찾아서 모든 rows 표시

# 특정 rows 삭제
df.drop(pd.to_datetime("20170402"))
df.drop([pd.to_datetime("20170402"), pd.to_datetime("20170403")])

# 특정 columns 삭제
df.drop("E", axis=1) # axis=1 는 column 선택 옵션
df.drop(["A","E"], axis=1)

DataFrame Fuctions 데이터프레임 분석용 함수 사용

import numpy as np
import pandas as pd
import matplotlib.pyplot  as plt

data = [[1.4,    np.nan],
        [7.1,      -4.5],
        [np.nan, np.nan],
        [0.75,     -1.3]]
df = pd.DataFrame(data, columns=["one", "two"], index=["a", "b", "c", "d"])


# 합계 구하기
df.sum(axis=0)    # column 합계
df.sum(axis=1)    # row 합계
df["one"].sum()   # one 라는 column 합계
df.loc["b"].sum() # b 라는 row 합계


# .mean 함수를 이용한 평균값 구하기
df.mean(axis=1, skipna=False)


# .mean, .min 함수를 이용하여 NaN 채우기
one_mean = df.mean(axis=0)["one"]
two_min  = df.min(axis=0)["two"]

df["one"] = df["one"].fillna(value=one_mean)
df["two"] = df["two"].fillna(value=two_min)


# 그래프: Box plot and Histogram
df["one"].plot.box()
plt.show()

df["one"].plot.hist()
plt.show()

df2 = pd.DataFrame(np.random.randn(6, 4),
                   columns=["A", "B", "C", "D"],
                   index=pd.date_range("20160701", periods=6))

df2["A"].corr(df2["B"])
df2["A"].cov(df2["B"])
df2.corr()
df2.cov()


# 데이터 정렬하기
dates = df2.index
random_dates = np.random.permutation(dates)
df2 = df2.reindex(index=random_dates, columns=["D", "B", "C", "A"])

df2.sort_index(axis=0) # row 이름으로 정렬 (오름차순)
df2.sort_index(axis=1) # column 이름으로 정렬 (오름차순)
df2.sort_index(axis=0, ascending=False) # row 이름으로 정렬 (내림차순)
df2.sort_index(axis=1, ascending=False) # column 이름으로 정렬 (내림차순)

df2.sort_values(by="D") # D column 값으로 정렬
df2.sort_values(by="B") # B column 값으로 정렬


# 두 가지 이상의 column 으로 정렬
df2["E"] = [1, 2, 2, 3, 3, 3]
df2["F"]= ["kim", "lee", "lee", "kim", "lee", "hong"]
df2.sort_values(["E", "F"])

데이터 분석 예제 - lendig club loan data

Lending Club 홈페이지에서 받을 수 있는 데이터로 작성된 예제입니다.

import numpy as np
import pandas as pd

loan = pd.read_csv("loan.csv", sep=",")

loan.shape # (887379, 74)
loan.columns # Index(['id', 'member_id', 'loan_amnt', 'funded_amnt', 'funded_amnt_inv', 'term', 'int_rate', 'installment', 'grade', 'sub_grade', 'emp_title', 'emp_length', 'home_ownership', 'annual_inc', 'verification_status', 'issue_d', 'loan_status', 'pymnt_plan', 'url', 'desc', 'purpose', 'title', 'zip_code', 'addr_state', 'dti', 'delinq_2yrs', 'earliest_cr_line', 'inq_last_6mths', 'mths_since_last_delinq', 'mths_since_last_record', 'open_acc', 'pub_rec', 'revol_bal', 'revol_util', 'total_acc', 'initial_list_status', 'out_prncp', 'out_prncp_inv', 'total_pymnt', 'total_pymnt_inv', 'total_rec_prncp', 'total_rec_int', 'total_rec_late_fee', 'recoveries', 'collection_recovery_fee', 'last_pymnt_d', 'last_pymnt_amnt', 'next_pymnt_d', 'last_credit_pull_d', 'collections_12_mths_ex_med', 'mths_since_last_major_derog', 'policy_code', 'application_type', 'annual_inc_joint', 'dti_joint', 'verification_status_joint', 'acc_now_delinq', 'tot_coll_amt', 'tot_cur_bal', 'open_acc_6m', 'open_il_6m', 'open_il_12m', 'open_il_24m', 'mths_since_rcnt_il', 'total_bal_il', 'il_util', 'open_rv_12m', 'open_rv_24m', 'max_bal_bc', 'all_util', 'total_rev_hi_lim', 'inq_fi', 'total_cu_tl', 'inq_last_12m'], dtype='object')

# 특정 column 만 추출한 후 NaN 포함된 관측치 제거
loan2 = loan[["loan_amnt", "loan_status", "grade", "int_rate", "term"]]
loan2 = loan2.dropna(how="any")

loan2.head()
loan2.tail()

# categorical data 확인
loan2["loan_status"].unique() # array(['Fully Paid', 'Charged Off', 'Current', 'Default', 'Late (31-120 days)', 'In Grace Period', 'Late (16-30 days)', 'Does not meet the credit policy. Status:Fully Paid', 'Does not meet the credit policy. Status:Charged Off', 'Issued'], dtype=object)
loan2["grade"].unique() # array(['B', 'C', 'A', 'E', 'F', 'D', 'G'], dtype=object)
loan2["term"].unique() # array([' 36 months', ' 60 months'], dtype=object)

loan2.shape # (887379, 5)


# 기간별(term) 대출금액 합계
term_to_loan_amount_dic = {}
unique_term = loan2["term"].unique()

for term in unique_term:
    loan_amount_sum = loan2.loc[loan2["term"]==term, "loan_amnt"].sum()
    term_to_loan_amount_dic[term] = loan_amount_sum

# loan status 별 대출금액 합계
total_status_category = loan2["loan_status"].unique()
bad_status_category = total_status_category[[1, 3, 4, 5, 6, 8]]

loan2["bad_loan_status"] = loan2["loan_status"].isin(bad_status_category)
bad_loan_status_to_grades = loan2.loc[loan2["bad_loan_status"] == True, "grade"].value_counts()
bad_loan_status_to_grades.sort_index()

loan2["loan_amnt"].corr(loan2["int_rate"])
bad_loan_status_to_grades.to_csv("bad_loan_status.csv", sep=",")

Tag Cloud

R    SQL    classification    demension reduction    jekyll    python    regression    supervised   
Hyeongjun Kim

Hyeongjun Kim

Financial Economist, Data Scientist, and Hearthstone Player

rss facebook twitter github youtube mail spotify lastfm instagram linkedin google google-plus pinterest medium vimeo stackoverflow reddit quora quora