텀프로젝트 코드 분석-2
보기전에 주의점
2022년 4월 14일 데이터를 기준으로 프로젝트가 작성되어있습니다.
2022년 4월 14일 데이터를 기준으로 프로젝트가 작성되어있습니다.
각 물자별 손실량 그래프
fig = px.bar(military_total_losses_cost, x ='equipment_name', y='losses_cost',text_auto=True,
title=f'Russian Equipment Losses cost in Ukraine War \n({last_date})')
fig.update_traces(textfont_size=18, textangle=0, cliponaxis=False)
fig.update_layout(
xaxis_title="Equipment Name",
yaxis_title="Cost of Equipment Losses",
font_size = 18
)
fig.update_yaxes(tickformat='$,',ticksuffix='M')
fig.show()
이 그래프는 plotly로 그렸다. 데이터는 military_total_losses_cost
값을, x 축을 equipment_name
칼럼으로, y축을 losses_cost
값으로 했다.
데이터 기준 날짜가 매우 중요하므로 타이틀에 미리 계산해둔 last_date
값을 표시하도록 해주었다.
update_traces
에서 textfont_size
로 제목 값을 조정해주었고, update_layout
값으로 x,y축 이름과 각 폰트 사이즈도 똑같이 18pt로 설정해주었다.
마지막으로 내가 계산한 값은 $M 단위이므로 y축에도 그에 맞는 단위를 넣어줘야 그래프를 직관적으로 이해할 수 있기 때문에, update_yaxex
라는 메서드로 조정을 해주었다.
tickformat
은 단위를 설정하는 옵션인데,$
를 넣으면 달러 단위 표시를 넣어주고,,
를 넣으면 1000 단위로 세미콜론을 넣어준다.tickformat
에 어떠한 옵션을 넣을 수 있고 어떻게 바뀌는지는 여기서 확인할 수 있다.ticksuffix
옵션으로 마지막에 M 표시를 추가했다. 만약 맨앞에 넣고싶으면tickprefix
로 하면 된다.
각 군 편제별 총 손실량 그래프
fig = px.bar(
military_total_losses_cost, x='unit_type', y='losses_cost',color='equipment_name',text_auto=True,
title=f'Russian Equipment Losses cost in Ukraine War \n({last_date})'
)
fig.update_layout(
xaxis_title="Unit Type",
yaxis_title="Cost of Equipment Losses",
font_size = 18
)
fig.update_yaxes(tickformat='$,',ticksuffix='M')
fig.show()
위의 Bar 그래프와 다를건 하나도 없다. 그저 x축을 equipment_name
대신에 unit_type
으로 정의했을 뿐인데, 각 유닛 타입에 맞는 것들이 stack 되어 이런 식으로 바로 보여주는 것이다.
매우 편리하고 직관적인 방식인것 같다.
각 군 편제별 총 손실량 Pie 그래프
fig = px.pie(military_total_losses_cost, values='losses_cost', names=military_total_losses_cost['unit_type'],
title=f'Percentages of Russian Equipment Losses cost in Ukraine War \n({last_date})')
fig.update_layout(
font_size = 22
)
fig.show()
이 그래프도 plotly의 pie
메서드를 이용해서 그렸다. values
값과 names
값으로 내가 원하는 종류의 값을 자동으로 비율을 계산해서 그래프로 보여준다. 설명이 필요없는 직관적인 그래프인것 같다.
만약 군 편제별이 아니라 군 물자별로 비율을 알고 싶다면? (갑자기 생각나서 추가로 작성해본다.)
fig = px.pie(military_total_losses_cost, values='losses_cost', names=military_total_losses_cost['equipment_name'],
title=f'Percentages of Russian Equipment Losses cost in Ukraine War \n({last_date})')
fig.update_layout(
font_size = 22
)
fig.show()
이런식으로 나온다.
일자별 군 물자 손실 그래프
rank_list = military_total_losses_cost['equipment_name'].values.tolist()
plt.figure(figsize=(14,8))
sns.set_style("darkgrid")
for equip in rank_list:
sns.lineplot(x='date', y=equip, data=loss_eq_Calc, marker='o')
plt.xlabel('Date',fontsize=18)
plt.ylabel('Cost of Equipment Losses', fontsize=18)
plt.title('Russian Equipment Losses Cost in Ukraine War 2022')
plt.legend(labels=rank_list)
plt.gca().yaxis.set_major_formatter(mticker.FormatStrFormatter('$%.1fM')) # matplotlib에서 y축 단위설정 함수
plt.show()
line 그래프는 seaborn의 그래프로 그렸다.
먼저 여러 개의 선을 넣기 위해서 각 선분의 이름을 리스트화하여 가질 rank_list
를 만들었다. military_total_losses_cost
에서 equipment_name
칼럼의 value
를 .tolist()
하여 리스트로 들고있게 된다.
그리고 plt.figure
로 그래프를 그릴 준비를 하고, .set_style
로 darkgrid
스타일을 적용했다.
그 다음 for문을 이용해서 rank_list
를 하나씩 받아와 각각 y축으로, x축은 date
로 지정하여 그렸다.
xlabel
, ylabel
로 x,y축 이름 지정, 그리고 ply.legend()
로 범례를 표시하였다.
matplotlib에서 plotly의 tickformat
같이 단위를 설정하는 메서드는 .gca().yaxis.set_major_formatter
이다.
이 안에서 mticker.FormatStrFormatter
로 설정을 해줘야 하는데, mticker
는 코드분석-1에서 라이브러리 임포트에 있는 import matplotlib.ticker as mticker
이다.
그리고 mticker
의 FormatStrFormatter
메서드에서 하는 포메팅은 조금 다른데, 한번에 표시가 가능하다.
- 먼저 앞뒤에 원하는 문자를 넣는다. 나의 경우는
$
와M
표시인데, 만약 이것만 넣은mticker.FormatStrFormatter('$M')
이라면 실제 값은 아래와 같이 나올 것이다. - 그러므로 중간에는 실제 들어갈 값을 넣어줘야 하는데, 그게
%
표시이고, 원하는 소수점 표시를 위해.1f
를 넣어준 것이다. 만약 정수를 원한다면%i
를 써주면 된다. 이에 대한 예시는 참고한 사이트를 보면 될 것이다. - 지금 생각해보면 정수표시가 맞는것 같다... 그래서 코드만 수정했다.
일자별 군 편제별 손실 그래프
# 각 일자별 손실량 합산
total_loss_cost_per_day = loss_eq_Calc.iloc[:,:1].copy()
total_loss_cost_per_day['ground_units'] = loss_eq_Calc[ground_units].sum(axis=1)
total_loss_cost_per_day['naval_units'] = loss_eq_Calc[naval_units].sum(axis=1)
total_loss_cost_per_day['air_units'] = loss_eq_Calc[air_units].sum(axis=1)
print(total_loss_cost_per_day.tail())
> 실행결과
date ground_units naval_units air_units
43 2022-04-09 7831.585 4200 4976.73
44 2022-04-10 7855.969 4200 5010.96
45 2022-04-11 7875.017 4200 5053.82
46 2022-04-12 8804.554 4200 5156.51
47 2022-04-13 8952.336 4200 5216.34
여기서 조금의 전처리가 있는데, 군 편제별로 일자별 손실누적량을 계산하려면 새로운 데이터프레임이 필요하다는 결론이 나와서 새로 구성했다.
먼저 내가 필요한 값은 행은 전부, 열은 date
와, 미리 계산해둔 값의 합산값만 있으면 되기 때문에, 먼저 total_loss_cost_per_day
객체에 행 전체와 열 date
만 copy()
해왔다.
그리고 ground_units
라는 새로운 열에, 미리 만들어둔 ground_units
객체에 있는, 육군 군물자들의 값에 대한 sum()
값을 axis=1
으로 하였으므로 ground_units
에 존재하는 'APC', 'military auto', 'tank', 'field artillery', 'MRL','anti-aircraft warfare', 'mobile SRBM system'
이 시리즈들을 전부 들고와서, 각 행별로 각 열들이 전부 더해져서 total_loss_cost_per_day['ground_units']
의 각 행에 전부 들어가게 된다.
나머지 naval_units, air units
들도 같은 작업으로 해주었고, 그 값을 출력한 값이 정상적으로 나옴을 알 수 있다.
# 그래프 그리기
units = ['ground_units', 'naval_units', 'air_units']
plt.figure(figsize=(14,8))
sns.set_style("darkgrid")
for unit in units:
sns.lineplot(x='date', y=unit, data=total_loss_cost_per_day, marker='o')
plt.xlabel('Date',fontsize=18)
plt.ylabel('Cost of Equipment Losses Per Unit',fontsize=18)
plt.title('Russian Military Units Equipment Losses Cost in Ukraine War 2022')
plt.legend(labels=units)
plt.gca().yaxis.set_major_formatter(mticker.FormatStrFormatter('$%iM'))
plt.show()
위에서 느낀것처럼 지금은 정수형태로 y축을 수정한 상태의 그래프이다. 그 외에는 일자별 군 물자 손실 그래프와 다른점은 없다.
일자별 각 군물자 순 손실량 그래프
cost_per_day = loss_eq_Calc.iloc[:,:1].copy()
cost_per_day['losses'] = loss_eq_Calc.iloc[:,2:].copy().sum(axis=1)
cost_per_day['losses_day'] = cost_per_day['losses'].copy()
for i in range(1,last_index+1):
cost_per_day['losses_day'][i] = (cost_per_day['losses_day'][i] - cost_per_day['losses'][i-1])
cost_per_day.drop('losses',axis=1,inplace=True)
print(cost_per_day.head())
> 실행결과
date losses_day
0 2022-02-25 1677.224
1 2022-02-26 649.720
2 2022-02-27 4.000
3 2022-02-28 757.310
4 2022-03-01 268.910
fig = px.bar(cost_per_day, x ='date', y='losses_day',text_auto=True,
title=f'Russian Equipment Losses cost per Day in Ukraine War \n({last_date})')
fig.update_traces(textfont_size=18, textangle=0, cliponaxis=False, textposition='outside')
fig.update_layout(
xaxis_title="Date",
yaxis_title="Cost of Equipment Losses",
font_size = 18
)
fig.update_yaxes(tickformat='$,.0f',ticksuffix='M')
fig.show()
순 손실량을 알려면 또 새로운 Dataframe으로 값을 저장해야 한다고 생각해서 cost_per_day
객체를 새로 만들었다. 먼저 date
열을 copy()
해오고, 임시 losses
행을 만들어 총 군물자의 합산값을 넣어주었다. 그리고 losses_day
행을 만들어 현재 날짜의 손실값 - 그 전날의 합산값
으로 간단하게 순 손실량을 구해주었다.
하지만 여기서 문제가 있었는데, SettingWithCopyWarning
에러였다. 찾아보니 본 데이터프레임에서 데이터를 가져온 서브 데이터프레임의 값을 변경할 경우, 본 데이터프레임에 존재하는 View에 대해 어떠한 방식으로 처리해야 할지 정해진 답이 없기 때문에, 무조건 본 데이터 프레임에서 가져오는 서브 데이터프레임은 .copy()
메서드를 사용해서 들고 오라는 것이다. 그래서 새로운 View를 생성한 뒤에 처리를 하라고 하는데...
여러가지 방법을 시도해 본 결과 그냥 데이터프레임에 있는 데이터를 변경하려는 행위 자체에서 발생하는 터라 결국 해결방법은 못찾았다...
어쨌든 결과는 무사히 잘 나오고, 그걸 plotly의 Bar 그래프로 나타냈다. 아쉬운 점으로는 date
의 갯수가 많아서 Bar의 폭이 좁고 그래서 y축 데이터의 값이 얼마인지 각 Bar에 조그맣게 나와서 식별하기가 어렵다는 점이다.
📜결론
텀프를 마무리할때는 다 잘 한줄 알았는데, 포스트를 작성하면서 미진했던 점도 많이 발견했고. 여러모로 부족한 점이 있어서 수정을 했다. 역시 테스팅은 여러번 해야 하는 것 같다는 작은 깨달음도 얻었고,
이러한 방식으로 내가 작성한 코드를 다시 분석하니 코드를 쓰면서 느꼈던 내용, 왜 이러한 코드를 썼는지 등등이 체득이 된것 같다. 처음에는 이러한 시간보다 코드 더 쓰는게 맞지 않나 라는 안일한 생각을 했지만. 이렇게 리뷰하고 되돌아보는 과정이 매우 중요함을 다시금 깨달았다.
이러한 프로젝트 뿐만 아니라 내가 배울 다른 데이터관련 정보들을 포스팅해보는 것도 매일은 아니더라도 일주일에 한번 이상은 해야겠다 싶은 생각을 했다.
Author And Source
이 문제에 관하여(텀프로젝트 코드 분석-2), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@galion/텀프로젝트-코드-분석-2저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)