R言語でマクドナルドの業績をウォーターフォール可視化

##マクドナルドの損益計算書を取得します

2020年12月期（連結）の営業利益が312億9000万円と、9年ぶりに最高益を記録したマクドナルドの損益計算書（PL）のウォーターフォール図を作ってみました。
**「ggplot2」**が装備する、矩形描画のための**「geom_rect」**を使います。
※プログラム言語初心者レベルなので、冗長性のあるコードになっているかもしれません。ご容赦ください。

ウォーターフォール図作成の参考にしたのは
[https://qiita.com/tayohei@github/items/1a19e1b5a05dccfa8c71](https://qiita.com/tayohei@github/items/1a19e1b5a05dccfa8c71)
[https://www.jigsawacademy.com/waterfall-charts-using-ggplot2-in-r/](https://www.jigsawacademy.com/waterfall-charts-using-ggplot2-in-r/)
の2つです。

マクドナルドの決算データはこちらから取得しました（単位：百万円）。

[https://www.mcd-holdings.co.jp/ir/summary/#hd_summary_05](https://www.mcd-holdings.co.jp/ir/summary/#hd_summary_05)

支出はマイナスにしました。

<img width="300" alt="ウォーターフォール1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/e5ff8477-e09d-c10d-609a-0a3d007d2f3f.png">

一応、確認のための計算をしました。
サイトにある数字は十万円以下が丸められているので、確認した数字の最後の桁が微妙に異なりますが、このまま使います。

<img width="500" alt="ウォーターフォール2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/b88b4b99-839e-fe6c-5b2c-5f1749ec5b38.png">

データフレーム型にします。

```r
pl_data <- data.frame(
    items = c("売上高", "売上原価", "販売費及び一般管理費", "営業外収益", "営業外費用", "特別利益", "特別損失", "法人税住民税及び事業税", "法人税等調整額", "当期純利益"),
    amount = c(288332, -230075, -26966, 1421, -1286, 0, -870, -10140, -226, 20186),
    stringsAsFactors=F
)

pl_data #データ確認
                    items  amount
1                  売上高  288332
2                売上原価 -230075
3    販売費及び一般管理費  -26966
4              営業外収益    1421
5              営業外費用   -1286
6                特別利益       0
7                特別損失    -870
8  法人税住民税及び事業税  -10140
9          法人税等調整額    -226
10             当期純利益   20186
```
##「ggplot2」用にデータを加工します

今回は**「ggplot2」**を使います。
データの加工をします。

```r
#ggplot2に適用するためのデータ加工
#seq_along()はデータセットのインデックス化したベクトルを返
#データフレームの場合は列単位。リストの場合はリスト単位
pl_data$items <- as.factor(pl_data$items) #ファクター型に変換
pl_data$id <- seq_along(pl_data$amount) #上記参照
pl_data$type <- ifelse(pl_data$amount > 0, "収入", "支出") #「収入」「支出」がわかる列を追加
# items列の"売上高", "営業外損益"の行のtype列に"net" と追記。収入のネット金額
pl_data[pl_data$items %in% c("売上高", "営業外収益"), "type"]  <- "net" 
pl_data #データ確認
                    items  amount id type
1                  売上高  288332  1  net
2                売上原価 -230075  2 支出
3    販売費及び一般管理費  -26966  3 支出
4              営業外収益    1421  4  net
5              営業外費用   -1286  5 支出
6                特別利益       0  6 支出
7                特別損失    -870  7 支出
8  法人税住民税及び事業税  -10140  8 支出
9          法人税等調整額    -226  9 支出
10             当期純利益   20186 10 収入
```

累積値を追加します。

```r
pl_data$end <- cumsum(pl_data$amount) #cumsum は累積
pl_data #データ確認
                    items  amount id type    end
1                  売上高  288332  1  net 288332
2                売上原価 -230075  2 支出  58257
3    販売費及び一般管理費  -26966  3 支出  31291
4              営業外収益    1421  4  net  32712
5              営業外費用   -1286  5 支出  31426
6                特別利益       0  6 支出  31426
7                特別損失    -870  7 支出  30556
8  法人税住民税及び事業税  -10140  8 支出  20416
9          法人税等調整額    -226  9 支出  20190
10             当期純利益   20186 10 収入  40376
```

この後**「geom_rect」**を使い描画するので、矩形範囲を指定するための加工をします。

```r
#end列に　end列の1行目を外したものと、末尾に0を加えた ベクトルに差し替える
pl_data$end <- c(head(pl_data$end, -1),0)
pl_data #データ確認
                    items  amount id type    end
1                  売上高  288332  1  net 288332
2                売上原価 -230075  2 支出  58257
3    販売費及び一般管理費  -26966  3 支出  31291
4              営業外収益    1421  4  net  32712
5              営業外費用   -1286  5 支出  31426
6                特別利益       0  6 支出  31426
7                特別損失    -870  7 支出  30556
8  法人税住民税及び事業税  -10140  8 支出  20416
9          法人税等調整額    -226  9 支出  20190
10             当期純利益   20186 10 収入      0

#start列に　0とend列の-1行目にしたベクトルに差し替える
pl_data$start <- c(0, head(pl_data$end, -1))
pl_data #データ確認
                    items  amount id type    end  start
1                  売上高  288332  1  net 288332      0
2                売上原価 -230075  2 支出  58257 288332
3    販売費及び一般管理費  -26966  3 支出  31291  58257
4              営業外収益    1421  4  net  32712  31291
5              営業外費用   -1286  5 支出  31426  32712
6                特別利益       0  6 支出  31426  31426
7                特別損失    -870  7 支出  30556  31426
8  法人税住民税及び事業税  -10140  8 支出  20416  30556
9          法人税等調整額    -226  9 支出  20190  20416
10             当期純利益   20186 10 収入      0  20190

#列を並び替える
pl_data <- pl_data[, c(3,1,4,6,5,2)]
pl_data #データ確認
   id                  items type  start    end  amount
1   1                 売上高  net      0 288332  288332
2   2               売上原価 支出 288332  58257 -230075
3   3   販売費及び一般管理費 支出  58257  31291  -26966
4   4             営業外収益  net  31291  32712    1421
5   5             営業外費用 支出  32712  31426   -1286
6   6               特別利益 支出  31426  31426       0
7   7               特別損失 支出  31426  30556    -870
8   8 法人税住民税及び事業税 支出  30556  20416  -10140
9   9         法人税等調整額 支出  20416  20190    -226
10 10             当期純利益 収入  20190      0   20186

pl_data_bkup <- pl_data #バックアップ用
```

**「str」**でデータの型を確認します。

```r
str(pl_data)
'data.frame':	10 obs. of  6 variables:
 $ id    : int  1 2 3 4 5 6 7 8 9 10
 $ items : Factor w/ 10 levels "営業外収益","営業外費用",..: 7 6 8 1 2 5 4 9 10 3
 $ type  : chr  "net" "支出" "支出" "net" ...
 $ start : num  0 288332 58257 31291 32712 ...
 $ end   : num  288332 58257 31291 32712 31426 ...
 $ amount: num  288332 -230075 -26966 1421 -1286 ...

#なお、下記にすると、ggploto2実行時にエラーが出るfactor型でないといけない（後でtypeと併せてfactorに変換）
pl_data$items <- as.character(pl_data$items)

str(pl_data)
'data.frame':	10 obs. of  6 variables:
 $ id    : int  1 2 3 4 5 6 7 8 9 10
 $ items : chr  "売上高" "売上原価" "販売費及び一般管理費" "営業外収益" ...
 $ type  : chr  "net" "支出" "支出" "net" ...
 $ start : num  0 288332 58257 31291 32712 ...
 $ end   : num  288332 58257 31291 32712 31426 ...
 $ amount: num  288332 -230075 -26966 1421 -1286 ...

pl_data$type <- as.factor(pl_data$type) #ファクター型に変換
pl_data$items <- as.factor(pl_data$items) #ファクター型に変換

str(pl_data)
'data.frame':	10 obs. of  6 variables:
 $ id    : int  1 2 3 4 5 6 7 8 9 10
 $ items : Factor w/ 10 levels "営業外収益","営業外費用",..: 7 6 8 1 2 5 4 9 10 3
 $ type  : Factor w/ 3 levels "net","支出","収入": 1 2 2 1 2 2 2 2 2 3
 $ start : num  0 288332 58257 31291 32712 ...
 $ end   : num  288332 58257 31291 32712 31426 ...
 $ amount: num  288332 -230075 -26966 1421 -1286 ...
```

##「ggplot2」と「geom_rect」を使います

**「geom_rect」**を使います。
**xmin、xmax、ymin、ymax**で矩形範囲を指定しています。

```r
library(ggplot2)
#geom_rect は　長方形描く。0.45+0.45の幅の長方形
#0.5より小さければ矩形の間に隙間ができる
ggplot(pl_data, aes(items, fill=type)) + geom_rect(aes(x = items, xmin = id-0.45, xmax = id+0.45, ymin = end, ymax = start)) + theme_gray (base_family = "HiraKakuPro-W3")
#base_family = "HiraKakuPro-W3"は、Macでの文字化け回避用
```

<img width="800" alt="ウォーターフォール3" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/60dfe1ff-2aee-3e1a-df89-b3704a128284.png">

しかし、このままだとx軸の表示順番が以下のようになっています（最後の行）。
順番を入れ替えます。

```r
pl_data$items
 [1] 売上高                 売上原価               販売費及び一般管理費  
 [4] 営業外収益             営業外費用             特別利益              
 [7] 特別損失               法人税住民税及び事業税 法人税等調整額        
[10] 当期純利益            
10 Levels: 営業外収益 営業外費用 当期純利益 特別損失 特別利益 売上原価 ... 法人税等調整額

#ファクターの水準の順序を入れ替える
#http://cse.naro.affrc.go.jp/takezawa/r-tips/r/16.html
#上記を参考に、factor関数でlevels引数を指定
pl_data$items <- factor(pl_data$items, levels=c("売上高", "売上原価", "販売費及び一般管理費", "営業外収益", "営業外費用", "特別利益", "特別損失", "法人税住民税及び事業税", "法人税等調整額", "当期純利益"))
pl_data$items #データ確認
[1] 売上高     売上原価   販管費     営業外損益 特別損益   税金       利益      
Levels: 売上高 売上原価 販管費 営業外損益 特別損益 税金 利益
```

再度描画します。
※下記のように「Ignoring unknown aesthetics: x 」というメッセージが出るのですが、まだ調べがついていません。
※意図通りの可視化はできているので、このまま進めます。
　

```r
#再描画設定
options(scipen=100) #Y軸が指数表示になるのでそれを回避
pl_plot <- ggplot(pl_data, aes(items, fill=type)) + geom_rect(aes(x = items, xmin = id-0.45, xmax = id+0.45, ymin = end, ymax = start)) + theme_gray (base_family = "HiraKakuPro-W3")+theme(axis.text.x = element_text(size = 6))
pl_plot
```

<img width="800" alt="ウォーターフォール4" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/7e1b8a4b-effc-e1f5-c9df-3f9fe4f443c5.png">

各バーにテキストを追加します。

```r
#矩形領域に文字を入れる
library("stringr")
pl_plot2 <- pl_plot + geom_text(aes( #文字追加。位置は以下で指定
        x = id ,
        y = (start+end)/2, #グラフの中央に文字を配置
        label = str_c(items,"\n",amount),
        family = "HiraKakuPro-W3" #Macでのプロット内ので文字化け防止
    )
    ,size = 3,)+ labs(x = "", y = "amount", fill= "") #軸ラベル付与
#sizeの位置はgeom_text(aes(label=***), size=x.x)

#描画実行
pl_plot2
```

<img width="800" alt="ウォーターフォール5" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/79e1f8d7-9c77-17b2-7b44-c86e2185874d.png">

**了**