【営業マンの時短術】ウォーターフォールを描け

月次、四半期など報告書のための図表作りを少しでも楽にしたい。その一念のみです。
より良い方法があればぜひご教示ください。
#課題
最近、本社上層部が入れ替わり、ウォーターフォールで売上増減要因を明確化せよ、とのお達し。
エクセルでも出来るが、ひとつひとつ作るのは邪魔くさい！
#元データ
こればっかりは自分で作らなきゃいけない。

```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とか面倒なので敢えて無視。

```python: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]
```
#いざプロット

```python: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")
```
#完成
![Waterfall.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120538/2ff5ec35-8482-a32a-d589-202a178af278.png)

#売上は悪くとも、せめて見栄え良く
###カラーパレット
本当はもう少し色に気を配りたいところ。カンパニーカラーなどのカラーパレットがあるのであれば、他にも共通で使えるように別のファイルにリストしておいてimportすると便利。

```python: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"
```

グレースケールは結構大事！。

###増減のラベル

```python:
# 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")
```
![Waterfall_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120538/7ec7a84e-cce1-3346-2d1b-42354ee16b6f.png)

###矢印の追加

```python:
# 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="-|>"))
```

![Waterfall_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120538/bef458fc-afe7-855a-d9a3-504b79796704.png)


なんだかんだ書きましたが、図表に時間をかける前に上層部を説得できる~~言い訳~~説明を考えよう。