[EDA] 파이썬을 활용한 데이터 분석하기(Pandas)

정환우·2021년 7월 13일
1

데이터 분석

목록 보기
1/3
post-thumbnail

현재 데이터를 분석하는 업무를 맡아서 개인공부를 했는데, 한번 쭉 정리해보려고 쓰는 글입니다.

사용하는 모듈들

가장 핵심적인 것 : pandas
데이터를 위한 것 : json, numpy
알고리즘 활용 : mlxtend
그래프 등을 활용한 시각화를 위한 것 : matplotlib.pyplot, dataprep.eda

import pandas as pd
from dataprep.eda import plot, plot_correlation, plot_missing   # dataprep.eda의 plot사용. 보기 훨씬 깔끔하다.
import matplotlib.pyplot as plt
from matplotlib import rc
import numpy as np
import json
from pandas import json_normalize
from mlxtend.preprocessing import TransactionEncoder        # apriori 사용하려고 추가하는 모듈들.
from mlxtend.frequent_patterns import apriori
from mlxtend.frequent_patterns import association_rules


rc('font', family='AppleGothic')
plt.rcParams['axes.unicode_minus'] = False  # matplotlib.pyplot에서 한글 깨지는걸 해결.

다 추가하면 이렇게 된다.
모든 것을 한번에 다 사용하지는 않기 때문에 정리가 필요하지만, 일단 다 추가하면 이렇다.

아래 두 코드들은 matplotlib.pyplot에서 x축,y축에 범례를 한글로 쓰면 깨지는 것을 방지하기 위해 삽입한 코드다.

데이터 분석하기

목표

내가 맡은 업무는 데이터간의 상관 관계를 분석하는 것. 하지만 이런 데이터를 다루는 게 태어나서 처음해보는 것이기 때문에, 데이터에 대한 전반적인 지식과 데이터를 다루는 형식, 방법, 알고리즘 등에 대해서 공부를 했다.

EDA 과정

EDA : Exploratory Data Analysis. 탐색적 데이터 분석.

이 과정을 크게 4단계로 나누어 보면

  1. 분석의 목적을 확인하고, 어떠한 변수가 있는지 살펴본다.
  2. 데이터에 문제가 없는지 head와 tail값을 살펴보고, 이상치와 결측치에 관한 추가적인 탐색을 실시한다.(NaN값은 어떻게 처리할지 등)
  3. 데이터의 개별 속성값을 관찰하면서, 예측한 범위와 분포인지, 아니라면 왜 아닌지 생각하고 분석한다.
  4. 데이터의 속성 간의 관계에 초점을 맞추어서 상관관계나 시각화 등 찾아내지 못했던 패턴을 발견해낸다.

말이 좀 어렵게 느껴질 수 있는데, 간단하게 추리면 데이터를 살펴보면서 당연히 코딩의 기본인 null값이나 예상치 못한 값은 어떻게 처리를 할 것인지 생각을 해보고, 나머지 데이터들을 잘 만져서 원하는 정보를 뽑아내면 되는 것이다.

Dataframe 만들고 추출하기

보통 데이터를 직접 코드를 짜는 경우는 거의 없을 것이고, 대부분은 csv나 json등 데이터 파일로 받을 것이다. 나도 csv파일로 받았기 때문에, csv파일을 읽어서 Pandas DataFrame으로 만들어주고, 그 데이터프레임안에서 정보들을 추출해 내면 된다.

data = pd.read_csv("ts_data.csv", low_memory=False) # " "안에는 파일명
pd.set_option('display.max_columns',None)   # columns 항목이 굉장히 길어도 생략안하고 끝까지 출력하게 해주는 코드.

이런식으로 코드를 짜면 data는 pandas dataframe 형식의 변수로, 이 변수 안에 데이터가 다 들어가 있는 것이다.

예를 들어, 데이터프레임안에 '오늘 할 일' 항목이 있다고 치면,

print(data['오늘 할 일'])

이렇게 코드를 쓰면 그 항목에 대한 데이터가 쫙 나오는 것이다. Pandas 너란 녀석... 참 좋아..

아무튼 이렇게 생겼고, 내가 받은 데이터에는 columns수가 130개, Rows수가 25000개로 꽤 크다. csv파일만 몇십메가가 되고, 워크스페이스 하나 수정하려면 맥북 프로가 렉이 걸리는 그런 상황이어서, 코드 안에서 데이터를 쉽게쉽게 살펴보려고 원하는 데이터 몇 개를 추출하려고 한다.

추출 방법

이 방법이 무조건 옳은 건 절대 아니고, 그냥 내 생각인데, 원본 데이터를 헤치지 않고 원하는 데이터만 쏙 빼내서 다른 데이터프레임에 복사를 하는 방식을 사용했다.

근데 이제 여기서 중요하게 생각해야 할 점이, 내가 원하는 데이터는 nested한 데이터 였다. 그러니까 예를 들면

data['오늘 할일'] = {'아침' : '운동', '점심' : '휴식', '저녁' : '공부', '새벽' : '게임'}

뭐 이런식으로 생긴거다. 데이터안에 또 데이터가 있다.
근데 또 Pandas가 쩌는게 이걸 다 지원해준다. 너란 녀석...!

저 데이터가 어떻게 생긴 것처럼 보이는가? Dict나 Json처럼 보이지 않는가?
그럼 저 데이터가 dict나 json으로 두고 해주면 된다.
근데 여기서 중요한 점은, 파이썬에서 Json은 작은 따옴표가 아니라 큰 따옴표로 나타내야 하기 때문에, replace를 이용해주어 따옴표를 다 바꾸어 주어야 한다.

또, 무턱대고 데이터에 접근하면 데이터의 index가 출력에 나오기 때문에, iloc이나 loc 함수를 사용하여 접근해 주어야 한다. 이보다 더 좋은 접근 방법이 없진 않겠지만, 인덱스에 접근하는 함수 중에는 이게 시간이 가장 짧은 함수라고 들었다.

전체 코드는

# 정확한 방법인지는 확인이 안되지만, 먼저 dataframe을 만들어서 하나를 추가해놓고 계속 추가하는 방식.
risk_df = pd.DataFrame()

data_size = 200 # 원하는 데이터 사이즈. 최댓값은 len(data)로 해야 한다.
for i in range(0,data_size):
    v2 = data['RISK_V2'].iloc[i]
    dict_v2 = v2.replace("'", "\"")
    json_string = json.loads(dict_v2)
    json_df = json_normalize(json_string)
    risk_df = pd.concat([risk_df,json_df],ignore_index=True)    #DataFrame 합쳐주기. ignore_index = True를 해야 index가 재구성 된다.

#   // 지금은 안쓸거니까 .risk_df = risk_df.reindex(sorted(risk_df.columns),axis=1)   # 보기 편하게, columns name을 정렬한다.

new_df = risk_df[['ASSETS_VAL_6','ASSETS_VAL_7','ASSETS_VAL_8','ASSETS_VAL_9','ASSETS_VAL_10']]
new_df = pd.concat([data['TW_DMG_PORT'].head(data_size),new_df],axis=1) # 이건 열 합쳐주기. axis = 1 이면 열 합치는 것.

이런식으로 코드를 완성했다.

그래프 만들기

그래프는 그냥 플롯 모듈을 사용하기 때문에, 모듈에 알맞게 데이터를 만들어서 넣어주기만 하면 된다.
모듈은 원래있던 데이터를 x,y값에 넣고 그래프를 그려주는 것 뿐, 데이터는 우리가 만드는 거니까 훨씬 쉽다고 할 수있다.
(dataprep.eda는 데이터를 넣으면 엄청나게 가공해서 그래프를 그려주는데, 처음부터 사용하는 건 좋지 않다고 생각한다.)


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

sorts = sorted(country_index.items())
country,index = zip(*sorts)
Index = np.arange(len(sorts))
plt.bar(Index,index)
plt.xticks(Index,country)
plt.xlabel('국가 이름',fontsize=15)
plt.ylabel('공격 횟수',fontsize=15)
plt.show()

이런식이다.
country_index라는 딕셔너리에 원하는 데이터를 넣고 x 축에 국가 이름, y축에 공격 횟수를 넣어준 것이다.

상관분석 하기

A priori Algorithm을 사용하였는데, 이 알고리즘은 F/P Growth Algorithm과 함께 따로 게시글을 올릴 예정이다.

이것도 결국 모듈에 데이터를 넣어주는 것인데, 중요한 것은 Pandas에서는 DataFrame을 사용하지만 이 개념은 DataSet을 사용하기 때문에 데이터의 형식을 바꿔주는 작업이 필요하다.

그리고, 바꿔주면서 원하는 결과가 나올 수 있도록 살짝 살짝 손봐줘야 한다. 나는 여기서 시간을 줄일 방법을 굉장히 고민을 많이했는데, 고민만 많이하고 아직 성과를 내진 못했다.

index를 직접 접근하는 게 굉장히 비효율적이라고 해서 group함수를 이용하여 만져보려고 했는데, 깔끔하게 만들어내지 못했다.

for i in range(0,200):
    str_list = []
    val = port80_df.iloc[i]
    for j in range(0,len(clist)):
        new_str = str(clist[j]) + " : " + str(val[clist[j]])
        str_list.append(new_str)
    dataset.append(str_list)

# 수작업으로 데이터셋 만들기..
te = TransactionEncoder()
te_result = te.fit(dataset).transform(dataset)
df = pd.DataFrame(te_result, columns=te.columns_) #위에서 나온걸 데이터프레임으로 변경
frequent_itemsets = apriori(df, min_support=0.5, use_colnames=True)
aroutput = association_rules(frequent_itemsets, metric="confidence", min_threshold=0.3) # 이걸 다시 상관 분석으로.
print(aroutput.to_markdown())

일단 for문은 데이터 셋을만드는 과정인 것이다. 왜 저렇게 만들었냐면, 데이터의 이름은 다른데 값은 정수형으로 겹치는 것이 있어서 코드명 마냥 이름과 값을 붙여서 다른 것으로 인식하도록 만들어주려고 했다.

그리고 아래는 mlxtend모듈을 사용하려고 조작해주는 것이다.

이런식으로 조작하면 antecedent support, consequent support, support, confidence, lift, leverage, conviction 이 항목들에 대한 수치가 나온다. 이것들에 대한 설명도 알고리즘 설명과 같이 하도록 하겠다!

오늘 포스팅은 이정도로 끝내야지.

profile
Hongik CE

0개의 댓글