23  plotly

23.1 インタラクティブなグラフ

Rでインタラクティブなグラフを作成したい場合には、rglパッケージ(Murdoch and Adler 2023)や、Javascriptのインタラクティブグラフィックライブラリであるd3.jsを使用したライブラリであるr2d3 (Strayer, Luraschi, and Allaire 2022)を用いるなど、様々な方法があります。

このようなインタラクティブなグラフ作成パッケージの中では、plotly (Sievert 2020)が機能が多彩かつ記述の方法もシンプルで非常に分かりやすい優れたライブラリです。

plotlyライブラリのロード
pacman::p_load(plotly)

以前はRでインタラクティブなグラフを作成しても、Rが実行されているPC上でのみ確認ができただけで、他の人とグラフを共有するすべがほとんどありませんでした。しかし、ここ10年で、Rを用いてHTMLの文書を作成するライブラリ(RMarkdown (Allaire et al. 2023; Xie, Allaire, and Grolemund 2018; Xie, Dervieux, and Riederer 2020)Quarto)や、Webアプリケーションを作成するためのライブラリ(Shiny(Chang et al. 2024)が公開され、インタラクティブなグラフを共有するしくみが構築されました。

Web上でのインタラクティブなグラフの多くはd3.jsで構築されていると思います。しかし、d3.jsの記法はやや特殊で、Rユーザーが使いこなすのはやや難しいです。plotlyは主にPythonのライブラリとして開発されていますが、Rやほかの言語での開発も行われています。記法もggplot2やRのデフォルトのグラフィック関数に近く、Rユーザーにも使いやすいものとなっています。

インタラクティブなグラフの使いどころは難しいですが、有効に用いれば、データを確認しやすく、見る人の興味を引くグラフを作成することができます。

23.2 散布図

plotlyでは、グラフはplot_ly関数で描画します。plot_ly関数の引数としてグラフのタイプ(type)を指定しない場合には、xy軸に指定した値に対応したグラフを描画してくれます。xにもyにも数値を指定すれば、散布図が自動的に選択されて、描画されます。xyなどの、ggplot2でのaesにあたる要素の指定では、データフレームの列名にチルダ(~)を付けます。チルダがないと、列名をうまく読み込むことはできません。

plot_ly関数で散布図
plot_ly(data = iris, x = ~Sepal.Length, y = ~Sepal.Width, color = ~Species)

ggplot2と同様に、colorsizeなどの引数に数値を取ることで、バブルチャートなどのグラフを作成することもできます。

plot_ly関数でバブルチャート
iris |> 
  plot_ly(x = ~Sepal.Length, y = ~Sepal.Width, color = ~Petal.Length, size = ~Petal.Width)

ggplot2でのscale_color_brewerのように、Color Brewerを用いた色の指定も行うことができます。配色の指定にはcolorsという引数を用います。

ColorBrewerの色指定
diamonds[sample(1:nrow(diamonds), 500),] |> 
  plot_ly(data = _, x = ~carat, y = ~price, color = ~carat, colors = "RdYlGn")

23.3 棒グラフ

xに因子、yに数値を与えると、plot_ly関数は自動的に棒グラフを描画します。逆にxに数値、yに因子を与えると、棒グラフが横向きになります。

棒グラフの描画
iris |> 
  group_by(Species) |>
  summarise(mSepal.Length = mean(Sepal.Length)) |> 
  plot_ly(x = ~Species, y = ~mSepal.Length, color = ~Species)

23.4 線グラフ

線グラフを描画する場合のxyの指定は散布図と同じです。線を加える場合には、mode="lines"もしくはmode="lines+markers"と指定します。"lines"で指定した場合には線のみ、"lines+markers"は点と線を描画する形になります。

mode="lines"で線グラフを描画
pacman::p_load(gapminder)
color_4 <- c("red", "blue", "green", "black") # 色をベクターで指定

gapminder::gapminder |> 
  filter(country == "Japan" | country == "China" | country == "United States" | country == "Australia") |> 
  plot_ly(x = ~year, y = ~gdpPercap, type = "scatter", mode = "lines+markers", color = ~country, colors = color_4)

23.5 3次元グラフ

3次元のグラフはrglで描画できますが、plotlyでも簡単に3次元グラフを作成することができます。plotlyで三次元グラフを作成する場合には、xyに加えて、z軸に相当する値を指定します。ただし、rglと同じように、3次元グラフはデータを認識しにくいため、3dグラフを用いるのではなく他のグラフ、例えばバブルチャートなどを選択する方がよいでしょう。

plotlyで3次元グラフ
iris |> 
  plot_ly(x = ~Sepal.Length, y = ~Sepal.Width, z = ~Petal.Length, color = ~Species, size = 0.1)

23.6 時系列プロット

x軸に日時データを指定すれば、簡単に時系列グラフを描画することができます。時系列プロットや線グラフを作成する場合には、plot_ly関数の返り値をadd_trace関数の引数にする形でも指定できます。

add_trace関数
data.frame(year = time(Nile), value = Nile) |> 
  plot_ly(type = "scatter", mode = "lines") |> 
  add_trace(x = ~year, y = ~value)

23.7 ウォーターフォールプロット

企業の財務状態などを表記する場合には、ウォーターフォールプロットが便利です。ウォーターフォールプロットでは、収益と支出の色を変え、収益はプラス方向、支出はマイナス方向の方向性を持った形で棒グラフで表現します。ウォーターフォールプロットを作図する場合には、type="waterfall"と指定します。

plotlyでは、ウォーターフォールプロットのほかにも、ろうそくチャートオープン-ハイ-ロー-クローズチャートなど、ビジネスや株価に関連したグラフを簡単に作成することができます。

waterfallプロット
x= c("Sales", "Consulting", "Net revenue", "Purchases", "Other expenses", "Profit before tax")
measure= c("relative", "relative", "total", "relative", "relative", "total")
text= c("+60", "+80", "", "-40", "-20", "Total")
y= c(60, 80, 0, -40, -20, 0)

data = data.frame(x = factor(x, levels = x), measure, text, y)

fig <- plot_ly(
  data, name = "20", type = "waterfall", measure = ~measure,
  x = ~x, textposition = "outside", y= ~y, text = ~text,
  connector = list(line = list(color = "rgb(63, 63, 63)"))) 

fig <- fig %>%
  layout(title = "Profit and loss statement 2018",
        xaxis = list(title = ""),
        yaxis = list(title = ""),
        autosize = TRUE,
        showlegend = TRUE)

fig

23.8 ggplotly

plotlyでは、ggplot2で準備したグラフをインタラクティブなグラフに簡単に変換することができます。ggplot2のグラフオブジェクトを変数に保存し、その変数をggplotly関数の引数にするだけで、ggplot2のグラフがインタラクティブなものに変換されます。

ggplotlyでインタラクティブなggplot2グラフ
p <- iris |> 
  ggplot(aes(x = Sepal.Length, y = Sepal.Width, size = Petal.Length, color = Species))+
  geom_point() 

ggplotly(p)