ill-identified diary

所属組織の見解などとは一切関係なく小難しい話しかしません

[R] 都知事選挙を題材に学ぶ ggplot2 の作例

この記事は最終更新日から3年以上が経過しています

概要

前回 (ggplot2 で積み上げ折れ線グラフ(エリアプロット)を作成する方法) に引き続き, ggpplot の作例を紹介する. 前回は時系列データから積み上げ折れ線グラフを作成したのに対し, 今回は2014年2月9日に行われた東京都知事選挙の結果という横断面データを用いてグラフを作成する. 具体的には, 以下のような作例を紹介する.

  • 棒グラフ (バープロット) を用いて候補者別・世代別得票数を可視化する
  • バープロットのデザインのバリエーションをいくつか紹介
    • 縦横を転置する方法
    • 円グラフに変換する関数

データフレームの作成

去る2014年2月9日に行われた東京都知事選のデータから棒グラフを作成する. ここでは, 【更新】東京都知事選挙(2014年2月9日実施)投票動向分析 で算出されている主要候補者別・世代別投票数の値を借りて作成する.

# source: http://www.jgnn.net/ls/2014/02/201429.html
vote <- data.frame(matrix(c(73954,230315,325399,291591,473307,718413,2112979,37339,132650,158198,145424,222066,286918,982595,22946,124288,148190,152014,259093,249532,956063,64141,126449,167988,95295,95295,61697,610865), nrow=4, ncol=7, byrow=T))
colnames(vote) <-c("twenties","thirties","forties","fifties","sixties","seventies","sum")
vote$candidates <- c("舛添氏", "宇都宮氏", "細川氏", "田母神氏")

この時点で, vote オブジェクトの中身は

  twenties thirties forties fifties sixties seventies     sum candidates
1    73954   230315  325399  291591  473307    718413 2112979     舛添氏
2    37339   132650  158198  145424  222066    286918  982595   宇都宮氏
3    22946   124288  148190  152014  259093    249532  956063     細川氏
4    64141   126449  167988   95295   95295     61697  610865   田母神氏

となっているはずである. この数値をもとに, 出処のサイトにあるような棒グラフを作成してみる. この場合, グラフの x 軸は各候補者のラベルに, y 軸は (世代別に色分けされた) 得票数の合計になる. ここでも前回同様, reshape2 パッケージの melt 関数を利用することになる.

library(ggplot2)
library(reshape2)
 
vote.melt <- melt(vote, id.vars="candidates", measure.vars=colnames(vote)[1:6])

今回も, 積み上げ棒グラフを作成するだけなら簡単に可能である.

(g.stack <- ggplot(vote.melt) + geom_bar(mapping=aes(x=candidates, y=value, group=variable, fill=variable), stat="identity") )

f:id:ill-identified:20140222231420p:plain

前回の geom_line() 等では, 積み上げグラフにするには position="stack" とすれば良かった. バープロットでも有効だが, 上の場合は省略できる. stat 引数は, デフォルトでは stat="bin" となっており, これはヒストグラムの用に x に対応する行の数をカウントしてプロットする. これは集計されてないデータをプロットする際には便利だが, 今回は既に集計されたものを用いるため, 不適当であり, stat="identity" を指定する((非集計データの場合は "stack" を使う)). さらに, 全ての棒の高さを1に揃え, 候補者ごとに投票した世代の比率を表したい場合は, position="fill" とする.

ggplot(vote.melt) + geom_bar(mapping=aes(x=candidates, y=value, group=variable, fill=variable), stat="identity", position="fill")

f:id:ill-identified:20140222231446p:plain

ただし, 既に参照元で示されているように, 分母 (=各候補者の総得票数, 各世代の有権者の総数) が大きくことなるため, このグラフは見る人に誤解を与える可能性が高い. 比率で表したグラフでは田母神氏に投票した40代が非常に多いように見えるが, 絶対数ではさほど多くない.

一方, 積み上げるのでなく, 横に並べたい (side-by-side chart) 場合, position="dodge" とする.

(g.dodge <- ggplot(vote.melt) + geom_bar(mapping=aes(x=candidates, y=value, group=variable, fill=variable), stat="identity", position="dodge") )

f:id:ill-identified:20140222231456p:plain

絶対数と比率を同時に比較したい場合は, この図が一番適しているのかもしれない.

デザインの洗練

さしあたって, 前回の記述を踏まえ,

  • 縦軸の目盛りを自然数表記に
  • ラベルを全て日本語に
  • 色を変更

といった変更をまとめて行う. これらは前回と同様の方法なので解説は省略.

label.gen <- c("20代", "30代", "40代", "50代", "60代", "70代以上")
(g.dodge2 <- g.dodge + scale_y_continuous(labels=function(x) x/10000) + labs(x="候補者", y="投票者数\n (万人)", title="2014年度東京都知事選挙\n主要候補者・世代別推定投票者数") + theme(axis.title.y = element_text(angle = 90*0, vjust = 1) ) + scale_fill_brewer(palette="Spectral", name="", labels=label.gen) )

さらに, 次のような変更を加える.

  • それぞれの棒にその候補者に占める比率を表示
  • 凡例をグラフ下部に移動
  • 候補者の並びを得票数順に.
vote.ratio <- function(x) paste(format(x/rep(vote$sum,6)*100, digits=2), "%", sep="") # 比率を計算し, 書式を整える関数を定義
( g.dodge2 <- g.dodge2 + geom_text(aes(x=candidates, y=value, ymax=value, label=vote.ratio(value), group=variable ), position=position_dodge(width=1, height=1), size=3 ) + theme(legend.position="bottom") + scale_x_discrete(limits=c("田母神氏", "細川氏", "宇都宮氏", "舛添氏")) )

geom_text() 関数を使い, パーセントを表示した. position=“dodge” は geom_text には適用できず, %表示のテキストが重なってしまうため, position_dodge() で代用した. 凡例の位置は, theme(legend.position="bottom") で下部に移動. もちろん, “left”, “top” 等も可能. 候補者の並びについては, グラフを作成する前に候補者名を factor型として扱い, levels を設定することでも変えられるが, すでにグラフを作ってしまったため, scale_x_discrete() 関数で並び替えている.

f:id:ill-identified:20140222231539p:plain

縦横を転置する方法

coord_flip() 関数で棒グラフを横に伸ばすことができる.

g.dodge2 + coord_flip()

theme() で与えた軸ラベルの設定は, coord_flip() で変わらないようなので注意.

f:id:ill-identified:20140222231635p:plain

円グラフに変換する方法

棒グラフに対し + coord_polar(theta = "y") とすると, 縦軸の大きさを角度で表した円グラフ (pie chart) として出力できる. 3D円グラフについては, ggplot2 は3D円グラフの作成に向いてないし, 作成に使わないでください.

(画像省略)

参考