텀프로젝트 코드 분석-1

보기 전에 주의점

2022년 4월 14일 데이터를 기준으로 프로젝트가 작성되어있습니다.

프로젝트 전체 코드 Github

라이브러리 목록

import seaborn as sns # 그래프 라이브러리, matplotlib 확장형
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker # x, y축 스타일 변경을 위한 라이브러리
import plotly # 그래프 라이브러리이지만 matplotlib와 다르게 반응형이고 디자인도 깔끔해서 더 좋음.
import plotly.graph_objs as go
import plotly.express as px
from plotly.subplots import make_subplots
import numpy as np
import pandas as pd # 데이터 처리 관련 라이브러리

데이터 전처리 1

loss_eq=pd.read_csv(r'Ukrine_Russia_War\archive\russia_losses_equipment.csv')

print(loss_eq.tail())

> 실행결과 
          date  day  aircraft  helicopter  tank   APC  field artillery  MRL  military auto  fuel tank  drone  naval ship  anti-aircraft warfare  special equipment  mobile SRBM system
43  2022-04-09   45       151         136   705  1895              335  108           1363         76    112           7                     55               25.0                 4.0
44  2022-04-10   46       152         137   722  1911              342  108           1384         76    112           7                     55               25.0                 4.0
45  2022-04-11   47       154         137   725  1923              347  111           1387         76    119           7                     55               25.0                 4.0
46  2022-04-12   48       157         140   732  1946              349  111           1406         76    124           7                     63               25.0                 4.0
47  2022-04-13   49       158         143   739  1964              358  115           1429         76    132           7                     64               25.0                 4.0

먼저 데이터를 로드해서 본 결과이다. 본 데이터는 각 군물자에 대한 파괴 count 값만 나열되어 있다.



eq_cost = [21.43, 12.8, 0.5, 0.039, 2, 2.3, 0.06, 600, 115, 20]
loss_eq.drop(['fuel tank', 'drone', 'special equipment'], axis=1, inplace=True) #계산불가능 값 제외
loss_eq['date'] = pd.to_datetime(loss_eq['date']) ## Object를 datetime으로 형변환

먼저, 각 군물자 column 순서에 맞게 내가 조사한 비용 값을 eq_cost에 넣었다.
그리고 먼저 로드한 loss_eq 값에서 내가 필요없다고 생각하는 fuel tank, drone, special equipment 값을 제외했다.
pandas에서 어떠한 데이터프레임을 건드리는 메서드에서 axis는 중요한 값인데, default는 0이며 행의 값을 의미한다. axis = 1 이라면 이 메서드는 열을 건드리는, column에 대한 메서드가 된다. 그래서 각 이름에 맞는 열들이 삭제되었다.
그리고 inplace로 값을 바로 바꿔주었다. 이 값이 기본은 False인데, True로 하지 않으면 대입연산자로 다시 넣어주어야 한다.
현재 loss_eq값에서 date column은 오브젝트 형태인데, 이걸 datetime으로 형변환을 해주었다.



데이터 전처리 2

loss_eq_Calc = loss_eq.copy()
i = 0
for x in loss_eq.columns.to_list()[2:]: # 계산
    loss_eq_Calc[x] = loss_eq[x] * eq_cost[i]
    i += 1
loss_eq_Calc.fillna(0,inplace=True) # 결측치 제거
print(loss_eq_Calc.tail())

> 실행결과 # 단위는 $M임.
         date  day  aircraft  helicopter   tank     APC  field artillery    MRL  military auto  naval ship  anti-aircraft warfare  mobile SRBM system
43 2022-04-09   45   3235.93      1740.8  352.5  73.905              670  248.4          81.78        4200                   6325                80.0
44 2022-04-10   46   3257.36      1753.6  361.0  74.529              684  248.4          83.04        4200                   6325                80.0
45 2022-04-11   47   3300.22      1753.6  362.5  74.997              694  255.3          83.22        4200                   6325                80.0
46 2022-04-12   48   3364.51      1792.0  366.0  75.894              698  255.3          84.36        4200                   7245                80.0
47 2022-04-13   49   3385.94      1830.4  369.5  76.596              716  264.5          85.74        4200                   7360                80.0

그 다음 내가 원하는 각 군물자별 손실비용에 대한 데이터를 가공하기 위해서 loss_eq_Calc 값을 만들었다. 기본적인 구조는 같기 때문에 loss_eq에서 copy해왔다.

그리고 loss_eq에서 내가 계산에 필요한 column은 1열 date, 2열 day를 제외한 모든 열이기 때문에 .columns.to_list() 로 리스트화 하여 3열부터 차례대로 넘겨받는 형태로 for문을 돌렸다.
그리고 loss_eq_Calc.fillna() 매서드를 이용해, 0인 값이라 NaN으로 나온 값들을 모두 0으로 바꿔주었다.

실행결과를 보면 잘 나온것을 확인 할 수 있다.



데이터 전처리 3

last_index = len(loss_eq_Calc.index)-1
last_date = loss_eq_Calc['date'][last_index].date().strftime("%d %B %Y")
military_total_losses_cost = loss_eq_Calc.iloc[-1:,2:].sort_values(by=[last_index],axis=1,ascending=False).T # .T로 인덱스와 열을 바꿔줌
military_total_losses_cost.rename(columns={last_index:'losses_cost'}, inplace = True)

military_total_losses_cost 라는 객체가 나오는데, 결국 loss_eq_Calc 데이터는 날짜마다 데이터가 적층되어 오기 때문에 최종일이 총 데이터의 합계가 된다.
그래서 마지막 일자의 계산값만 가지고 그래프를 만들기 위해 새로운 객체를 만들었다.

먼저 마지막 index의 값과 date의 값은 알고 있지만, 데이터는 계속 추가되기 때문에 저렇게 생성하였고 military_total_losses_costloss_eq_Calc.iloc[-1:,2:]의 값들을 sort_values()함수로 정렬된 값을 넘겨받게 된다.

  • loss_eq_Calc.iloc[-1:,2:] 이게 무슨 뜻인가? iloc은 뒤에 나올 좌표값을 바탕으로 dataframe에 접근하는 방식이다. -1: 은 뒤에서부터 첫번째. 즉 마지막 값을 의미하고 2:는 3열부터 라는 뜻이다.
  • sort_values() 함수에서는 by=[last_index]last_index에 있는 값에 대해 axis=1이므로 열의 값을 ascending=False이니 내림차순으로 정렬하라는 뜻이다.
  • 여기서 마지막에 .T이 있는데 이것은 행과 열을 바꿔주는 것이다. 즉 원래는 military_total_losses_cost의 열이 aircraft, helicopter, tank .... 이였으나 이게 인덱스로 가게 된다.

마지막으로 military_total_losses_cost.rename() 함수를 쓴 이유는 그래프 생성 편의성을 위해 원래 형태에선 열의 이름이 last_index의 값으로 들어가 있는 것을 losses_cost로 이름을 바꾸어 준 것이다.



데이터 전처리 4

# 그래프 x,y축 지정을 위한 전처리

military_total_losses_cost.reset_index(inplace=True)
military_total_losses_cost.rename(columns={'index':'equipment_name'},inplace=True)
print(military_total_losses_cost)

> 실행결과
          equipment_name  losses_cost
0  anti-aircraft warfare     7360.000
1             naval ship     4200.000
2               aircraft     3385.940
3             helicopter     1830.400
4        field artillery      716.000
5                   tank      369.500
6                    MRL      264.500
7          military auto       85.740
8     mobile SRBM system       80.000
9                    APC       76.596

마지막으로, 그래프에 그냥 index 형태로 x축 지정을 했어도 됐겠지만 그러면 우리가 원하는 순서가 아니라 index의 영어 사전순서대로 배치될 것이기 때문에 reset_index로 인덱스를 다시 지정하고, 원래 인덱스는 열의 이름이 index인 새로운 열로 만들어졌을 것이기에 그 이름을 equipment_name으로 rename 해주었다.

실행 결과를 보면 원하는대로 잘 나온것을 확인할 수 있다.



데이터 전처리 5

# 각 카테고리 별 군대 구분
air_units = ['helicopter', 'aircraft']
naval_units = ['naval ship']
ground_units = ['APC', 'military auto', 'tank', 'field artillery', 'MRL','anti-aircraft warfare', 'mobile SRBM system']

def murge_category(unit):
    if unit in ground_units:
        return "Ground Units"
    elif unit in naval_units:
        return "Naval Units"
    else:
        return "Air Units"
    
military_total_losses_cost['unit_type'] = military_total_losses_cost['equipment_name'].apply(lambda x : murge_category(x))


print(military_total_losses_cost)

> 실행결과
          equipment_name  losses_cost     unit_type
0  anti-aircraft warfare     7360.000  Ground Units
1             naval ship     4200.000   Naval Units
2               aircraft     3385.940     Air Units
3             helicopter     1830.400     Air Units
4        field artillery      716.000  Ground Units
5                   tank      369.500  Ground Units
6                    MRL      264.500  Ground Units
7          military auto       85.740  Ground Units
8     mobile SRBM system       80.000  Ground Units
9                    APC       76.596  Ground Units

전처리가 참 길다... 그다음 각 군물자에 맞게 군대 구분을 해야 군대에 대한 합산 값이나 그래프를 만들 수 있기 때문에 이러한 방식으로 전처리를 했다.

pandas dataframe에서 ['column_name'] 을 붙인다면 원래 있는 열이라면 시리즈를 불러오고, 없다면 column_name이라는 새로운 시리즈를 붙여주는 방식이다.
여기에 .apply() 메서드로 lambda를 활용해서 넘겨받는 각 값에 대해 murge_category메서드를 적용해서 나온 값을 넘겨주어라 라는 뜻이 된다.

결과를 보면 잘 적용된 모습을 볼 수 있다.

📜 결론

어쩌다 보니 전처리만 한세월 적었다. 그만큼 데이터 시각화에 있어서 전처리가 중요하다는 뜻이 아닐까?!! 다음 포스트에는 그래프에 어떻게 데이터를 넣었는지 어떠한 방식으로 그래프를 가공할 수 있는지 다뤄보려고 한다.

좋은 웹페이지 즐겨찾기