ggplot2 v3.3.0を使ってみた

ggplot2 v3.3.0のリリースが近々予定されています。新機能がいろいろあるのでかいつまんで紹介します。

詳しくはNEWS.mdをご参照ください。

after_stat(), after_scale(), stage()

  • The evaluation time of aesthetics can now be controlled to a finer degree. after_stat() supersedes the use of stat() and ..var..-notation, ad is joined by after_scale() to allow for mapping to scaled aesthetic values. Remapping of the same aesthetic is now supported with stage(), so you can map a data variable to a stat aesthetic, and remap the same aesthetic to something else after statistical transformation (@thomasp85, #3534)

これはけっこう便利な新機能なんですが、何を言っているのかわからないと思うので公式ブログを待ちましょう。 覚えておくこととしては、

  • ..変数名..という書き方はもう古い、これからはstat()だ」という情報はもう古い、これからはafter_stat()

ということです。

...いや、混乱しますよね。わかります。まあ古い書き方もまだまだサポートされるので、とりあえずこういうものもあるんだな、くらいに頭の片隅に置いておいていただければ。そのうち日本語でも解説を書きます(たぶん)

geom_sf()判例のタイプが自動で決まる

  • geom_sf() now determines the legend type automatically (@microly, #3646).

これはどういうことかというと、geom_sf()判例はデフォルトだとポリゴンで、点や線の地物に対して適切な凡例を出そうと思ったらshow.legendを自分で設定する必要があったんですが、

それは必要なくなった、ということです。こんなふうに自動で判別されます。

library(ggplot2)
library(sf)
#> Linking to GEOS 3.8.0, GDAL 3.0.2, PROJ 6.2.1
  
p <- st_sfc(st_point(1:2), st_point(3:4))
d <- st_sf(geometry = p, id = c("a", "b"))

ggplot(d) + geom_sf(aes(colour = id), size = 10)

scale_x_continuous()scale_y_continuous()n.breaks引数

  • scale_x_continuous() and scale_y_continuous() gains an n.breaks argument guiding the number of automatic generated breaks (@thomasp85, #3102)

scale_{x,y}_continuous()に目盛りの数を指定できるようになりました。便利。

p <- ggplot(mtcars) + 
  geom_point(aes(mpg, disp))

patchwork::wrap_plots(
  p + scale_x_continuous(n.breaks = 10),
  p + scale_x_continuous(n.breaks = 4)
)

binned scale

  • A new scale type has been added, that allows binning of aesthetics at the scale level. It has versions for both position and non-position aesthetics and comes with two new guides (guide_bins and guide_coloursteps) (@thomasp85, #3096)

これもけっこう大きな変更なので別途解説が必要ですが、連続値を自動でbinしてくれるスケールが追加されました。scale_*_binnedとかscale_*_steps()とかいう関数がそれです。例えば、scale_colour_steps()は、scale_colour_gradient()だと色がなめらかに変化するところを段階的に変化させます。

set.seed(902)

df <- data.frame(
  x = runif(100),
  y = runif(100),
  z1 = rnorm(100)
)

p <- ggplot(df, aes(x, y)) +
  geom_point(aes(colour = z1))

patchwork::wrap_plots(
  p + scale_colour_gradient() + ggtitle("gradient"),
  p + scale_colour_steps()    + ggtitle("binned")
)

guide_axis()

  • Position guides can now be customized using the new guide_axis(), which can be passed to position scale_*() functions or via guides(). The new axis guide (guide_axis()) comes with arguments check.overlap (automatic removal of overlapping labels), angle (easy rotation of axis labels), and n.dodge (dodge labels into multiple rows/columns) (@paleolimbot, #3322).

guide_axis()という関数で軸ラベルの指定が少し柔軟になりました。angletheme()での指定との兼ね合いが謎ですが、n.dodgeは使うと気持ちいいです。

# plot with overlapping text
p <- ggplot(mpg, aes(cty * 10, hwy * 10)) +
  geom_point() +
  facet_wrap(vars(class))

patchwork::wrap_plots(
  p,
  p + scale_x_continuous(guide = guide_axis(n.dodge = 2))
)

stat_contour_filled(), geom_contour_filled()

  • Added stat_contour_filled() and geom_contour_filled(), which compute and draw filled contours of gridded data (@paleolimbot, #3044).

これまでgeom_contour()は線しか引けなかったんですけど、塗りつぶしありのバージョンを描けるようになりました。

v <- ggplot(faithfuld, aes(waiting, eruptions, z = density))

patchwork::wrap_plots(
  v + geom_contour(),
  v + geom_contour_filled()
)

expansion()expand_scale()は非推奨に)

  • expand_scale() was deprecated in favour of expansion() for setting the expand argument of x and y scales (@paleolimbot).

これは主に内部的な改善なんですが、expand_scale()は非推奨になったようです。 今の所は中でexpansion()を呼んでるだけなのでどっちでも同じでは?という感じなんですが、今後変更を加えることを考えてこうしたのかな...

geom_ribbon()geom_area()の線

  • geom_ribbon() now draws separate lines for the upper and lower intervals if colour is mapped by default. Similarly, geom_area() now draws lines for the upper in the same case by default. If you want old-style full stroking, use outlier.type = "legacy" (#3503, @yutannihilation).

colourを指定するとgeom_ribbon()は上下に線が、geom_area()は上に線に出るようになりました。地味に便利かも。

df <- tibble::tibble(
  y = c(0, 0, 0, 0, 0, 1, 1.5, 1.7, 1.8), 
  upper_y = y + 0.2, 
  lower_y = y - 0.2,
  year = -4:4
)

ggplot(df, aes(year, y)) + geom_line() + 
  geom_ribbon(aes(ymax = upper_y, ymin = lower_y),
              linetype = 2, fill = "red", alpha = 0.1, colour = "black")

coord_flip()なしでX軸とY軸を入れ替えられるようになった

X軸とY軸を自在に入れ替えられるようになりました。どういうことかというと、 例えば、geom_bar()aes()ではxマッピングしてY方向に棒を生やすGeomです。 これを、xではなくてyマッピングすれば、自動で棒をX方向にしてくれる、というものです。

library(patchwork)

p1 <- ggplot(mpg, aes(x = class)) + geom_bar()
p2 <- ggplot(mpg, aes(y = class)) + geom_bar()

p1 * p2

とはいえ、方向を推測するのが常にうまくいくとは限りません。例えば、以下のコードでは、人間は変数名を見てidが系列名でvalueが値だと察することができますが、 ggplot2にはそんなことはわかりません。

df <- data.frame(id = 1:3, value = 1:3)
p3 <- ggplot(df, aes(id, value)) + geom_col()
p4 <- ggplot(df, aes(value, id)) + geom_col()

p3 * p4

こんなときにどうするかというと、orientationという引数で明示的に方向を指定することができます。 データによってflipしたりしなかったりする、というブレを防ぐために、スクリプト中で使うときには必ず指定しておいたほうがいいでしょう。

ggplot(df, aes(value, id)) + geom_col(orientation = "y")

感想

この1年くらいあんまり議論を追えてなかったので、こんな変更あったのか...。みたいなやつがけっこうあって勉強になりました。