UPDATE: 2023-09-03 14:47:52

はじめに

このノートでは損益決算書をウォーターフォールチャートで可視化することを目的としている。ウォーターフォールチャートを作ってくれるパッケージはあるものの、再現したい形とは少し異なっているので自作した内容をまとめた。

サンプルデータ

損益決算書(profit & loss statement)は言わずもがななので割愛する。今回使用するデータはEDINETにアップされている良品計画の有価証券報告書から損益計算書の部分の数字をお借りしている。EDINETからはXBRLやcsvの形式でもダウンロードができるが、少し加工が大変そうだったので、今回はPDFを転記することにした。

library(waterfalls)
library(tidyverse)
library(scales)

d <- read_csv('~/Desktop/ryohin-keikaku-fy44.csv')
d2 <- d %>% 
  select(item3, amount,type) %>% 
  filter(!is.na(amount)) %>% 
  mutate(amount = if_else(type == 'out', -1*amount, amount))
d2
## # A tibble: 13 × 3
##    item3                   amount type 
##    <chr>                    <dbl> <chr>
##  1 営業収益                496171 net  
##  2 営業原価               -261814 out  
##  3 営業総利益              234356 net  
##  4 販管費および一般管理費 -201582 out  
##  5 営業利益                 32773 net  
##  6 営業外収益                6067 in   
##  7 営業外費用               -1626 out  
##  8 経常利益                 37214 net  
##  9 特別利益                   224 in   
## 10 特別損失                 -4234 out  
## 11 税金等調整前当期純利益   33204 net  
## 12 法人税等                 -8426 out  
## 13 当期純利益               24778 net

ウォーターフォールチャート

ウォーターフォールチャートが作れるパッケージwaterfallsを利用して可視化する。ちなみにwaterfallという単数形の名前のパッケージも存在しているので注意。

waterfall(d2, calc_total = TRUE)

これは思い通りには可視化できなていない。今回のデータは、営業収益から営業原価を引いた営業総利益も同時に可視化したい。しかし、パッケージでは、このような使い方はおそらく想定されておらず、営業総利益がそのまま足しこまれてしまっている。そのほかの部分も同様に、計算が誤ったままになっている。そもそもウォーターフォールチャートの使い方とは異なる可能性があるが。

このあたりの調整が行うためには自分で作成する方法しかないっぽいので、自作することにした。geom_rect関数を利用するので、そのための開始点や終了点を前処理しておく。

d3 <- d2 %>% 
  mutate(
    id = row_number(),
    end = cumsum(if_else(id == 1 | type != 'net', amount, 0)),
    start = lag(end, 1, 0),
    start = if_else(type == 'net', 0, start),
    item3 = fct_reorder(item3, id),
    type = fct_relevel(type, 'out', 'net', 'in')
  ) 
d3
## # A tibble: 13 × 6
##    item3                   amount type     id    end  start
##    <fct>                    <dbl> <fct> <int>  <dbl>  <dbl>
##  1 営業収益                496171 net       1 496171      0
##  2 営業原価               -261814 out       2 234357 496171
##  3 営業総利益              234356 net       3 234357      0
##  4 販管費および一般管理費 -201582 out       4  32775 234357
##  5 営業利益                 32773 net       5  32775      0
##  6 営業外収益                6067 in        6  38842  32775
##  7 営業外費用               -1626 out       7  37216  38842
##  8 経常利益                 37214 net       8  37216      0
##  9 特別利益                   224 in        9  37440  37216
## 10 特別損失                 -4234 out      10  33206  37440
## 11 税金等調整前当期純利益   33204 net      11  33206      0
## 12 法人税等                 -8426 out      12  24780  33206
## 13 当期純利益               24778 net      13  24780      0

あとはこのデータを加工すれば、狙い通りの可視化が実現できる。

ggplot(d3, aes(item3, fill = type)) + 
  geom_rect(aes(x = item3, xmin = id - 0.4, xmax = id + 0.4, ymin = end, ymax = start), col = 'black') + 
  geom_text(aes(x = id, y = if_else(type == 'out', start, end), label = amount),
            size = 3, hjust = 0.5, vjust = -0.5) + 
  scale_y_continuous(labels = label_comma()) + 
  scale_fill_manual(values = c('net' = '#f8f8f8', 'in' = '#68a1ff', 'out' = '#f87268')) +
  labs(title = '株式会社良品計画-連結損益計算書-', 
       subtitle = '自2021年9月1日 至2022年8月31日',
       x = '費目', y = '単位:100万円') + 
  theme_bw() + 
  theme(text = element_text(size = 10, family='Droid Sans Japanese'),
        axis.text.x = element_text(angle = 60, hjust = 1),
        legend.position = 'none',
        plot.title = element_text(size = 15, hjust = 0.5),
        plot.subtitle = element_text(size = 10, hjust = 0.5))