【영업맨 때 단술】 워터폴을 그려라

월차, 분기 등 보고서를 위한 도표 만들기를 조금이라도 편하게 하고 싶다. 그 일념뿐입니다.
더 나은 방법이 있다면 꼭 가르쳐주세요.

도전



최근, 본사 상층부가 바뀌어, 워터폴로 매출 증감 요인을 명확화하라고,의 도달.
엑셀에서도 할 수 있지만, 하나하나 만드는 것은 방해!

원본 데이터



이것만은 스스로 만들어야 한다.

data.dat
2018, 1000
Factor A, 200
Factor B, -70
Factor C, 50
Factor D, 100
Factor E, -500
Factor F, 200
2019, 980

데이터를 읽고 성형



우선, pandas에서 읽는다. index라든지 귀찮기 때문에 감히 무시.

waterfall.py 전반
import matplotlib.pyplot as plt
import pandas as pd

# Read File
df = pd.read_csv("./data.dat", header=None)

# Data Preparation
df[2]=df[1]
for i in range(len(df)):
    if i==0 or i==len(df)-1:
        df.iloc[i,2] = 0
    else:
        df.iloc[i,1] = df.iat[i-1,1] + df.iat[i-1,2]

막상 플롯



waterfall.py 후반
# Plot parameter
graphTitle = "Waterfall"
ylabel = "Turnover [mil. JPY]"
barWidth = 0.5
clrLeft = "lightgray"
clrRight = "gray"
clrPos = "lightgreen"
clrNeg = "red"
# Plot
fig = plt.figure(figsize=(10,5))
fig.suptitle(graphTitle)
ax = fig.add_subplot()
ax.grid(which="major", axis="y", linestyle="--")
bottomBar = ax.bar(df[0], df[1], width=barWidth, linewidth=0, color="white")
upperBar = ax.bar(df[0],df[2], width=barWidth, linewidth=0, bottom=df[1])
# Colour
for i in range(len(df)):
    if df.iat[i,2] < 0.0:
        upperBar[i].set_color(clrNeg)
    else:
        upperBar[i].set_color(clrPos)
bottomBar[0].set_color(clrLeft)
bottomBar[len(df)-1].set_color(clrRight)
fig.savefig("Waterfall.png")

완성





판매가 나쁘더라도 적어도 멋지다.



컬러 팔레트



사실은 좀 더 색깔에 신경을 쓰고 싶은 곳. 컴퍼니 칼라등의 칼라 팔레트가 있다면, 그 밖에도 공통으로 사용할 수 있도록(듯이) 다른 파일에 리스트 해 두어 import 하면 편리.

CompanyColour.py
# Company Colour
MyCompanyColour = "#3F48CC"
MyPalette1  = "#211A1D"
MyPalette2  = "#8075FF"
MyPalette3  = "#F8F0FB"
MyPalette4  = "#CAD5CA"

# Gray Colour 
GrayScaleBlack  = "#000000"
GrayScale90 = "#1A1A1A"
GrayScale80 = "#333333"
GrayScale70 = "#4D4D4D"
GrayScale60 = "#666666"
GrayScale50 = "#7F7F7F"
GrayScale40 = "#9A9A9A"
GrayScale30 = "#B3B3B3"
GrayScale20 = "#CCCCCC"
GrayScale10 = "#E6E6E6"

그레이 스케일은 상당히 중요! .

증감 라벨


# Label for increments
for i in range(len(upperBar)):
    if i!=0 and i!=len(upperBar)-1:
        height = upperBar[i].get_height()

        if df.iat[i,2]<0:
            ax.annotate("{}".format(height),
                        xy=(upperBar[i].get_x()+upperBar[i].get_width()/2, upperBar[i].get_y()),
                        xytext=(0,3),textcoords="offset points", ha="center", va="bottom")
        else:
             ax.annotate("{}".format(height),
                        xy=(upperBar[i].get_x()+upperBar[i].get_width()/2, upperBar[i].get_y()+height),
                        xytext=(0,3),textcoords="offset points", ha="center", va="bottom")



화살표 추가


# additional arrow
for i in range(len(upperBar)):
    if i!=0 and i!=len(upperBar)-1:
        length = upperBar[i].get_height()
        x = upperBar[i].get_x() + upperBar[i].get_width()/2
        ys = upperBar[i].get_y()
        ye = ys+length
        ax.annotate("", xy=(x,ye), xytext=(x,ys),
                    arrowprops=dict(arrowstyle="-|>"))



왠지 썼습니다만, 도표에 시간을 걸기 전에 상층부를 설득할 수 있는 변명 설명을 생각하자.

좋은 웹페이지 즐겨찾기