Help us understand the problem. What is going on with this article?

ggplot2でウォータフォールチャート?滝グラフ?を描く

More than 1 year has passed since last update.

売上とか利益とかでよく見るこんなグラフです。
ウォータフォールプロット?滝グラフ?とか呼ばれるらしいです。初めて知りました。
image.png

例えばこんなデータで。

# サンプルデータ
sanple_data <- data.frame(
    費目 = c("売上高", "売上原価",  "販管費", "営業外損益", "特別損益", "税金"),
    金額 = c(3251, -720, -420, -850, -281, -311),
    stringsAsFactors=F
)

image.png
※数字は適当です。

パッケージを使うと楽。

いろいろ調べていると、お手軽なパッケージありました。
https://rkabacoff.github.io/datavis/Other.html#waterfall-charts

# インストールして
install.packages("waterfalls")
library("waterfalls")

# こんな感じで。
waterfall(
    sanple_data, 
    calc_total=TRUE,  # 収支の差分のところを描画する
    total_axis_text = "利益", # そこの文字列
    total_rect_text_color="black", # そこの線の色
    total_rect_color="goldenrod1"  # そこの線の塗りつぶし
) 

実行すると、、
image.png

なるほどらくちん。でも、こまごました部分はオプションを付けていくスタンスで、
できればggplotでスパっと描けないものかと調べてみて、

ggplotで描く

作図用のデータ作って、geom_rect で描く感じ。
http://tomoshige-n.hatenablog.com/entry/2014/08/11/235816
https://gist.github.com/rentrop/36f07b67cb6c4b82088e2115fee2498f
などを参考にしました。

作図用のデータを作る。

# 作図用のデータ作成
tmp <- sanple_data %>% 
mutate(
    end = cumsum( 金額 ), # 上端
    start = dplyr::lag(end, default = 0), # 下端
    type = if_else( 金額 >=0,"収入","支出"), # 色分けのため
    id = seq(1, n())
) %>% 
bind_rows(summarise(., 費目 = "利益", 金額 =last(end), start = 0, end = last(end), id = n()+1L, type = "利益")) # 収支の差分のところ

image.png

こんな感じ。よく読めはなるほどだけど、元データの項目名以外はコピペでいけそう。

グラフを描く

library("tidyverse")

# 可視化
tmp %>% ggplot(aes(費目, fill = type)) + 
    geom_rect(aes(
        x = 費目 ,
        xmin = id-0.5, xmax= id+0.5, # 隙間なくするなら0.5、隙間空けるなら小さくする
        ymin = end, ymax= start 
    )) +
    geom_text(aes( # 文字を入れる
        x = id ,
        y = (start+end)/2, # グラフの中央に
        label = str_c(費目,"\n",金額) 
    )) +
    labs(x = "", y = "金額", fill= "")

image.png
できた!

facetで複数描画する。

ggplotで描きたかったのは、facet_wrapで複数一度に書けるんじゃないかなと思ったゆえで。
下記みたいなデータで、、

library(tidyverse)

# サンプルデータ
sanple_data <- data.frame(
    費目 = c(
        "売上", "売上原価",  "販管費", "営業外損益", "特別損益", "税金",
        "売上", "売上原価",  "販管費", "営業外損益", "特別損益", "税金",
        "売上", "売上原価",  "販管費", "営業外損益", "特別損益", "税金"
    ),
    金額 = c(
        3251, -720,  -420, -850, -281, -311,
        4728, -1650, -130, -250, -975, -535,
        2560, -320,  -540, -90,  -154, -241
    ),
    支店 = c(
        rep("西日本",6),
        rep("東日本",6),
        rep("海外",6)
    ),
    stringsAsFactors=F
)

image.png

グラフを描く

# 作図用のデータ作成
tmp <- sanple_data %>% 
group_by(支店)%>%   # ※ここを追記
mutate(
    end = cumsum( 金額 ),
    start = dplyr::lag(end, default = 0),
    type = if_else( 金額 >=0,"収入","支出"),
    id = seq(1, n())
) %>% 
bind_rows(summarise(., 費目 = "利益", 金額 =last(end), start = 0, end = last(end), id = n()+1L, type = "利益"))

# 可視化
tmp %>% ggplot(aes(費目, fill = type)) + 
    geom_rect(aes(
        x = 費目 ,
        xmin = id -0.45, xmax = id + 0.45,
        ymin = end, ymax = start
    )) +
    geom_text(aes(
        x = id ,
        y=(start+end)/2,
        label=str_c(費目,"\n",金額)
    )) +
    labs(x = "", y = "金額", fill="") +
    facet_wrap(~支店)   # ※ここを追記

image.png

できた!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした