ggplot2 2.3.0(RC版)を使ってみた

次期バージョンのggplot2が来月末にリリース予定です。例によってこのニュースを追ってみます:

公式のアナウンスはこちら:

tidyeval

tidyevalについての詳しい解説は省きますが、使えるようになりました。これによって、

plot_iris <- function(x, y, group) {
  x_var <- rlang::enquo(x)
  y_var <- rlang::enquo(y)
  group_var <- rlang::enquo(group)
  
  ggplot(iris, aes(x = !!x_var, y = !!y_var, colour = !!group_var)) +
    geom_point()
}

みたいな関数が作れるようになります。

また、facet_wrap()facet_grid()でもtidyevalが使えます。 具体的には、vars()という関数で囲みます。

plot_iris_w_facet <- function(x, y, group) {
  x_var <- rlang::enquo(x)
  y_var <- rlang::enquo(y)
  group_var <- rlang::enquo(group)
  
  ggplot(iris, aes(x = !!x_var, y = !!y_var, colour = !!group_var)) +
    geom_point() +
    facet_wrap(vars(!!group_var))
}

facet_grid()rowscolsを別々に指定できるようになっています。 つまり、以下は等価です(個人的に、~のどっちが列でどっちが行か毎回間違えるので明示的に指定できるようになってうれしいですw)。

facet_grid(x ~ y + z)
facet_grid(rows = vars(x), cols = vars(y, z)

副作用として、aes()が返すのはシンボルのリストではなくquosureのリストになっているので注意しましょう(たぶんパッケージ開発者以外は気にする必要ないと思いますけど)。

geom_sf()

ggplot2 now has full support for sf with geom_sf() and coord_sf()

これについてはちょっと長くなりそうなので記事を分けます。 まあこんな感じで、sfのデータも簡単にプロットできますよ、という感じです。

nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"))
ggplot(nc) +
  geom_sf()

詳しくはこちら:

stat()

New syntax for calculated aesthetics. Instead of using aes(y = ..count..) you can (and should!) use aes(y = stat(count)).

statによる計算結果の一部は..count..みたいな名前で参照することができました。例えば、以下の2つは同じ結果になります。

ggplot(mpg, aes(class)) + geom_bar()
ggplot(mpg, aes(class, ..count..)) + geom_bar()

この..という謎の記法の代わりにstat()という関数が使えるようになりました。つまりこう。

ggplot(mpg, aes(class, stat(count))) + geom_bar()

今後はこっちを使ってくださいね、とのことです。

tagラベル

New tag label for adding identification tags to plots, typically used for labelling a subplot with a letter. Add a tag with labs(tag = "A"), style it with the plot.tag theme element, and control position with the plot.tag.position theme setting (@thomasp85).

labs()で設定できるラベルには、

  • title: タイトル。
  • subtitle: サブタイトル。タイトルの下に少し小さなフォントで表示される。
  • caption: 注意書き。右下に小さな字で表示される。データソースについての説明とかを書く。

がありました。これに、tagというのが加わります。こんな感じで、サブプロットをつくるときに便利なやつです。 タグをつけておくと、説明のときに「図1のAに示すように...」みたいに書けるので便利です。

library(ggplot2)
p1 <- ggplot(economics, aes(date, unemploy)) + geom_line() +
  labs(title = "econimics", tag = "A")
p2 <- ggplot(mpg, aes(class)) + geom_bar() +
  labs(title = "mpg", tag = "B")
gridExtra::grid.arrange(p1, p2, nrow = 1)

geom_segment()geom_curve()arrow.fill引数

geom_segment() and geom_curve() have a new arrow.fill parameter which allows you to specify a separate fill colour for closed arrowheads (@hrbrmstr and @clauswilke, #2375).

矢印の塗りの部分はarrow.fillで色を指定できるようになりました。

df <- data.frame(x1 = c(1, 1), x2 = c(4, 2), y1 = c(1, 1), y2 = c(2, 4))
ggplot(df, aes(x = x1, y = y1, xend = x2, yend = y2)) +
  geom_segment(arrow = arrow(ends = "last", type = "closed"), arrow.fill = "red", colour = "purple") +
  theme_minimal()

(ちなみにfillではマッピングできないからこうなってるわけですが、なんでなんだろう。geom_point()fillを受け付けるわけなのでマッピングできてもいい気がする...)

geom_point()shapeを文字列で指定

geom_point() and friends can now take shapes as strings instead of integers, e.g. geom_point(shape = "diamond") (@daniel-barnett, #2075).

これまで点の形は、謎めいた数字でしか指定できませんでした。

ggplot(data.frame(x = 1, y = 1)) +
  geom_point(aes(x, y), shape = 18, size = 30)

それが、こんな感じで文字列で指定できるようになります。

ggplot(data.frame(x = 1, y = 1)) +
  geom_point(aes(x, y), shape = "diamond", size = 30)

具体的に指定できる文字列はvignetteを見ればわかるようになるはずです(まだ反映されてない)。

position_dodge()

preserve引数

position_dodge() gains a preserve argument that allows you to control whether the total width at each x value is preserved (the current default), or ensure that the width of a single element is preserved (what many people want) (#1935).

position_dodge()を使う際に、各系列の幅を一定にするか("single")、全系列の幅を一定にするか("totla")が選べるようになりました。 たぶん前者が直感的なものですが、後方互換性のためデフォルトは"total"になっています。

df <- data.frame(x = rep(letters[1:3], each = 3), 
                 fill = factor(c(2,2,3, 1:3, 3,3,3)))

p1 <- ggplot(df, aes(x, fill = fill)) + 
  geom_bar(position = position_dodge(preserve = 'total')) +
  labs("(default)")

p2 <- ggplot(df, aes(x, fill = fill)) + 
  geom_bar(position = position_dodge(preserve = 'single'))

gridExtra::grid.arrange(p1, p2)

position_dodge2()

New position_dodge2() provides enhanced dodging for boxplots.

position_dodge()を箱ひげ図用に拡張した、というやつなんですけど、それ以外にも、

  • 系列を真ん中に寄せてくれる
  • バーとバーの間に少しパディングを入れてくれる

という違いがあります。さっきの結果と比べてみると分かりやすいでしょう。基本的にこっちを使っておけばよさそうです。

p1 <- ggplot(df, aes(x, fill = fill)) + 
  geom_bar(position = position_dodge(preserve = "single"))

p2 <- ggplot(df, aes(x, fill = fill)) + 
  geom_bar(position = position_dodge2(preserve = "single"))

gridExtra::grid.arrange(p1, p2)

stat_qq_line()

New stat_qq_line() makes it easy to add a simple line to a Q-Q plot, which makes it easier to judge the fit of the theoretical distribution (@nicksolomon).

Q-Qプロットを描くときに便利なやつです。

set.seed(3)
df <- data.frame(y = rt(200, df = 5))
p <- ggplot(df, aes(sample = y))
p + stat_qq() + stat_qq_line()

datetime_scale

Improved support for mapping date/time variables to alpha, size, colour, and fill aesthetics, including date_breaks and date_labels arguments (@karawoo, #1526), and new scale_alpha() variants (@karawoo, #1526).

Improved support for ordered factors. Ordered factors throw a warning when mapped to shape (unordered factors do not), and do not throw warnings when mapped to size or alpha (unordered factors do). Viridis is used as the default colour and fill scale for ordered factors (@karawoo, #1526).

だいたい内部的な改善。最後のはordered factorだけデフォルトのカラースケールが違うようになったという話です。

iris <- dplyr::mutate(iris, Species_ordered = ordered(Species))

p1 <- ggplot(iris, aes(Sepal.Width, Sepal.Length, colour = Species)) +
  geom_point()
p2 <- ggplot(iris, aes(Sepal.Width, Sepal.Length, colour = Species_ordered)) +
  geom_point()

gridExtra::grid.arrange(p1, p2)

expand_scale()

The expand argument of scale_*_continuous() and scale_*_discrete() now accepts separate expansion values for the lower and upper range limits. The expansion limits can be specified using the convenience function expand_scale().

スケールをちょっと伸ばしたいときに便利な関数。伸ばす量を割合で指定したいときはmult、絶対値で指定したいときはaddです。 こんな感じで指定します。

library(ggplot2)

iris <- dplyr::mutate(iris, Species_ordered = ordered(Species))

p <- ggplot(data.frame(x = 1:2 * 10, y = 1:2 * 10), aes(x, y)) + geom_line()

gridExtra::grid.arrange(
  # デフォルトだと、連続値は5%伸びる
  p,
  # 0を指定すると値の範囲ぴったりになる
  p + scale_x_continuous(expand = expand_scale(mult = 0)),
  # mult = 0.1だと両側に10%伸びる
  p + scale_x_continuous(expand = expand_scale(mult = 0.1)),
  # add = 0.1だと絶対値で両側に0.1伸びる
  p + scale_x_continuous(expand = expand_scale(add  = 0.1)),
  # 別々に指定することもできる
  p + scale_x_continuous(expand = expand_scale(add  = c(0, 0.3))),
  ncol = 1
)

Viridis

scale_colour_continuous() and scale_colour_gradient() are now controlled by global options ggplot2.continuous.colour and ggplot2.continuous.fill. These can be set to "gradient" (the default) or "viridis" (@karawoo).

New scale_colour_viridis_c()/scale_fill_viridis_c() (continuous) and scale_colour_viridis_d()/scale_fill_viridis_d() (discrete) make it easy to use Viridis colour scales (@karawoo, #1526).

matplitlibに負けてられるか!ということで(?)、ggplot2でもviridisカラーパレットが使えるようになりました。

連続値にはscale_*_viridis_c()を、離散値にはscale_*_viridis_d()を使います。

p1 <- ggplot(mpg, aes(displ, fill = trans)) +
  geom_histogram(position = position_dodge2(preserve = "single"), binwidth = 1) +
  theme_minimal()

p2 <- p1 + scale_fill_viridis_d()

gridExtra::grid.arrange(p1, p2)

カラーパレットには種類がいくつかあるので、?scale_viridisを参照しましょう。

上で見たようにordered factorにはすでにviridisがデフォルトになってますが、全体的にviridisをデフォルトで使いたければ.Rprofileに以下を指定しておくといいでしょう。

options(ggplot2.continuous.colour = "viridis", ggplot2.continuous.fill = "viridis")

geom_text()の凡例の文字を指定

Guides for geom_text() now accept custom labels with guide_legend(override.aes = list(label = "foo")) (@brianwdavis, #2458).

こんな感じ。絶対覚えられない...

d <- data.frame(
  x = c(1, 1, 2, 2),
  y = c(1, 2, 1, 2),
  t = c("a", "a", "b", "b")
)

ggplot(d, aes(x, y, colour = t, label = t)) +
  geom_text() +
  guides(
    color = guide_legend(
      override.aes = list(
        label = c(
          expression(alpha),
          expression(beta)
        )
      )
    )
  )

Created on 2018-05-27 by the reprex package (v0.2.0).

その他

ggplot_add()

Custom objects can now be added using + if a ggplot_add method has been defined for the class of the object (@thomasp85).

詳しくはこれを参照。

ggsave()dpi引数を文字列で指定

ggsave()'s DPI argument now supports 3 string options: "retina" (320 DPI), "print" (300 DPI), and "screen" (72 DPI) (@foo-bar-baz-qux, #2156).

これはちょっと便利そうかも。dpiにいつも何を指定していいかわからないのでありがたい。

reproducible jittering

position_jitter() and position_jitterdodge() gain a seed argument that allows the specification of a random seed for reproducible jittering (@krlmlr, #1996 and @slowkow, #2445).

seedが設定できるようになった。

library(ggplot2)

ggplot(mpg, aes(cyl, hwy, colour = year)) +
  geom_jitter(position = position_jitter(seed = 1))

感想

今回は、けっこう久々のアップデートなわけですが、内部的な改善が多くて既存のものへの変更はそんなに多くなさそうです。 とはいえ、予想外の変更があることはよくあるので、テストしましょう。