京橋のバイオインフォマティシャンの日常

南国のビーチパラソルの下で、Rプログラムを打ってる日常を求めて、、Daily Life of Bioinformatician in Kyobashi of Osaka

【R言語とWebスクレイピングとアニメーショングラフ】仮想通貨や株価変動をモーションチャートで観察してみた件【S&P100のスキャッチャープロット編】

はじめに

いま、このブログでは「アニメーショングラフ」推しなのですが、、、 「バー・チャート・レース」が少し見難いようにも思えてきて、 散布図(スキャッチャープロット)のモーションチャートをやってみることにしました。

この記事では、S&Pダウ・ジョーンズ・インデックスが算出しているアメリカの株価指数の1つである、SP100の各銘柄の時系列データ(日足)について、「モーションチャート(Motion chart)」を作成します。

SP100はちょうど100銘柄から構成されているので、100点のスキャッチャープロットとなります。

さぁ、モーションチャート作図をやっていきましょう。

関連記事

skume.net

skume.net

実行環境

実行環境
macOS Big Sur (バージョン11.5.2)
MacBook Air (M1, 2020)
チップ Apple M1
メモリ 16GB

パッケージ準備

今回使用する、Rパッケージを準備します。

ここをスキップして、以下のスクリプトを読み込むのでもOKです。

#パッケージ・インストール
pack <- c("rvest", "quantmod", "magrittr", "tidyr", "tidyverse", "plotly", "gapminder", "dygraphs", "htmltools")
install.packages(pack[!(pack %in% unique(rownames(installed.packages())))])

#ロード
for(n in 1:length(pack)){ eval(parse(text = paste0("library(", pack[n], ")"))) }; rm("n", "pack")

getSP100.Rスクリプトを読み込んでも、Rパッケージがインストールできます。

同時に、今回使用する、getSP100_list、SP100_ChartData、SP100_ChartData_modといった関数群を読み込まれます。

#スクリプトの読み込み
source("https://gist.githubusercontent.com/kumeS/e8dca57f2ba101b2ef9714ce59400460/raw/dfdcf08fdbc7fbd41eb909520c4bb0bc52adf460/getSP100.R")

SP100銘柄のデータ取得

https://en.wikipedia.org/wiki/S%26P_100

まず、getSP100_list関数では、ウェブスクレイピングを介して、ウィキペディアの該当ページからSP100の銘柄リストを取得します。

さて、下記を実行していきます。

#SP100銘柄リストの取得
SP100List <- getSP100_list()

#表示
head(SP100List)
#                       Company Ticker                 Sector
#1                        Apple   AAPL Information Technology
#2                       AbbVie   ABBV            Health Care
#3                       Abbott    ABT            Health Care
#4                    Accenture    ACN Information Technology
#5                        Adobe   ADBE Information Technology
#6 American International Group    AIG             Financials

次に、2022年年初からのSP100のデータを取得します。

#SP100のデータ取得: 実行時間 3分くらい
ChartData <- SP100_ChartData(Dat=SP100List, term=c("2022-01-01", "2022-12-31"))

#いったん、RDS保存
saveRDS(ChartData, "SP100_ChartData.Rds")

#ダウンロード
#browseURL("https://github.com/kumeS/Blog/raw/master/R_BarChart/Chart_03/SP100_ChartData.Rds")
#ChartData <- readRDS("SP100_ChartData.Rds")

#表示
head(ChartData)
#                       Company Ticker                 Sector       date close dclose dclose2 ranking
#1                        Apple   AAPL Information Technology 2022-01-03   100      0 #F0F5F0       1
#2                       AbbVie   ABBV            Health Care 2022-01-03   100      0 #F0F5F0       2
#3                       Abbott    ABT            Health Care 2022-01-03   100      0 #F0F5F0       3
#4                    Accenture    ACN Information Technology 2022-01-03   100      0 #F0F5F0       4
#5                        Adobe   ADBE Information Technology 2022-01-03   100      0 #F0F5F0       5
#6 American International Group    AIG             Financials 2022-01-03   100      0 #F0F5F0       6

このステップで、SP100の銘柄リストと値動きのデータが取得できました。

続いて、SP100_ChartData_mod関数で、データの補正を行います。

#データ補正: 全銘柄を使用
ChartData1 <- SP100_ChartData_mod(ChartData)

#表示
head(ChartData1)
#  Company Ticker      Sector CompanyTicker    CompanySector       date close dclose dclose2 ranking
#1      3M    MMM Industrials      3M (MMM) 3M (Industrials) 2022-01-03 100.0    0.0 #F0F5F0      64
#2      3M    MMM Industrials      3M (MMM) 3M (Industrials) 2022-01-04 101.4    1.4 #F0F5F0      38
#3      3M    MMM Industrials      3M (MMM) 3M (Industrials) 2022-01-05 101.0    1.0 #F0F5F0      40
#4      3M    MMM Industrials      3M (MMM) 3M (Industrials) 2022-01-06 100.1    0.1 #F0F5F0      46
#5      3M    MMM Industrials      3M (MMM) 3M (Industrials) 2022-01-07 101.2    1.2 #F0F5F0      42
#6      3M    MMM Industrials      3M (MMM) 3M (Industrials) 2022-01-10  99.8   -0.2 #FCF3F3      52

plotlyによるモーションチャート(motion chart)の作図

それでは、取得したSP100の値動きデータを使って、モーションチャートを作成します。 値動きの大きさによって、マーカーのサイズが変わるように設定します。

#のべ日の作成
ChartData1$Day <- as.numeric(ChartData1$date) - min(as.numeric(ChartData1$date)) + 1
#マーカーのサイズ
ChartData1$Size <- (4*abs(ChartData1$dclose)/100 +1)*5
#サイズの範囲
range(ChartData1$Size)
#[1]  5.00 21.58

#plot_ly実行
fig <- plot_ly(ChartData1,
    x = ~ranking, 
    y = ~close, 
    size = ~Size, 
    color = ~Sector, 
    frame = ~Day,
    text = ~CompanySector,
    hoverinfo = "text",
    hovertemplate = paste('ranking: %{x}', '<br>%{text}',
                          '<br>Relative: %{y}<extra></extra>'),
    type = 'scatter',
    mode = 'markers'
  ) %>%
  layout(title = 'SP100 Y2022', 
         plot_bgcolor = "#e5ecf650", 
         xaxis = list(title = 'Ranking'), 
         yaxis = list(title = 'Relative price'), 
         legend = list(title=list(text='<b>Sector</b>')))

#作図: 30秒くらいかかる
fig

#保存
fig %>% htmltools::save_html(file="SP100_motion_chart.html")

https://kumes.github.io/Blog/R_BarChart/Chart_03/02_SP100_motion_chart.html

散布図だと、プロットがガチャガチャしても、何だか許容できますね。

dygraphsによるインタラクティブな作図

dygraphsパッケージは、dygraphs JavaScriptチャート・ライブラリへのRインターフェースです。 Rで時系列データを図表化するために、豊富な機能を提供しています。

このdygraphsパッケージは、xts時系列オブジェクト(または、xtsに変換可能なあらゆるオブジェクト)を自動的にプロットします。

#ワイド型への変換
ChartData2 <- ChartData1[,c("CompanySector", "date", "close")]
ChartData2.s <- spread(ChartData2, key = CompanySector, value = close)

#行名を変更する
rownames(ChartData2.s) <- as.character(ChartData2.s$date)
ChartData2.s <- ChartData2.s[,-1]

#表示(一部)
head(ChartData2.s)
#           3M (Industrials) Abbott (Health Care) AbbVie (Health Care)
#2022-01-03            100.0                100.0                100.0
#2022-01-04            101.4                 97.6                 99.8
#2022-01-05            101.0                 97.2                100.3
#2022-01-06            100.1                 97.2                 99.9
#2022-01-07            101.2                 97.5                 99.6
#2022-01-10             99.8                 97.3                100.7

#5つのサンプリング
x <- sample(1:ncol(ChartData2.s), 5)

#5つの可視化
p2 <- dygraph(ChartData2.s[,x],
        main = "SP100 Y2022",
        ylab = "Relative price") %>%
  dyRangeSelector(height = 20)  %>%
  dyLegend(show = "follow", width = 250, hideOnMouseOut = T, labelsSeparateLines = T)

#可視化
p2

#保存
p2 %>% htmltools::save_html(file="SP100_dygraph_p2.html")

https://kumes.github.io/Blog/R_BarChart/Chart_03/06_SP100_dygraph_p2.html

dygraphはプロットはサンプル数が多くなるとあまり使い物にならないかも。。 せいぜい、3-5サンプルくらいまでかな。

まとめ

SP100銘柄の2022年年初からのモーションチャートを作成しました。

バーがガンガン動く「バーチャートレース」よりも、 散布図のモーションチャートの方が目に優しい気がします。 私だけかもですが。

補足

plotlyによるインタラクティブチャート + ハイライト

ハイライトした、plotlyチャートの作成をやってみました。

#表示
head(ChartData1)

#ハイライト表示
g <- highlight_key(ChartData1, ~Ticker)

#作図
p <- plot_ly(g) %>%
  group_by(Ticker) %>%
  add_lines(x = ~date, y = ~close, color = ~CompanySector) %>%
  layout(xaxis = list(title = ""),
         yaxis = list(title = "Changes (%)"), showlegend = F) %>%
  highlight(selected = attrs_selected(showlegend = FALSE)) %>% 
  highlight(on = "plotly_click", 
                off = "plotly_doubleclick",
                persistent = FALSE,
                color = "red",
                selected = attrs_selected(opacity = 0.5))

#可視化
p

#保存
p %>% htmltools::save_html(file="SP100_plot_ly_p.html")

https://kumes.github.io/Blog/R_BarChart/Chart_03/07_SP100_plot_ly_p.html

ggplotlyによるインタラクティブチャート

plotlyパッケージ内のggplotlyという関数で、ggplot2::ggplot()のオブジェクトを plotlyオブジェクトに変換できる。マジで!!

#表示
head(ChartData1)

#ggplotで作図
p <- ggplot(ChartData1,
       aes(x = date, y = dclose, 
           group = CompanySector, 
           color = Sector)) + 
  geom_line()

#ggplotで可視化
p

##Plotlyで可視化
p1 <- ggplotly(p)

#保存
p1 %>% htmltools::save_html(file="SP100_ggplotly_p1.html")

これが、ggplotで可視化した結果です。

ggplotで可視化した結果

これが、ggplotlyで可視化した結果です。

https://kumes.github.io/Blog/R_BarChart/Chart_03/04_SP100_ggplotly_p1.html

この変換はとても簡単で、感動的です。

plotlyによるモーションチャートの実行テスト

gapminderのデータセットには、 国や地域ごと平均余命、人口、一人当たりのGDPを経時データが含まれています。

#テストデータ
df <- gapminder

#表示
head(df)
#  country     continent  year lifeExp      pop gdpPercap
#  <fct>       <fct>     <int>   <dbl>    <int>     <dbl>
#1 Afghanistan Asia       1952    28.8  8425333      779.
#2 Afghanistan Asia       1957    30.3  9240934      821.
#3 Afghanistan Asia       1962    32.0 10267083      853.
#4 Afghanistan Asia       1967    34.0 11537966      836.
#5 Afghanistan Asia       1972    36.1 13079460      740.
#6 Afghanistan Asia       1977    38.4 14880372      786.

#plot_ly実行
fig <- plot_ly(df,
    x = ~gdpPercap, 
    y = ~lifeExp, 
    size = ~pop, 
    color = ~continent, 
    frame = ~year, 
    text = ~country, 
    hoverinfo = "text",
    type = 'scatter',
    mode = 'markers'
  )

#レイアウト
fig <- fig %>% layout(
    xaxis = list( type = "log" )
  )

#作図
fig

#保存
fig %>% htmltools::save_html(file="test_motion_chart.html")

https://kumes.github.io/Blog/R_BarChart/Chart_03/05_test_motion_chart.html

ffmpegによる、mov形式をgifに変換する

ターミナルを起動して、ffmpegで変換します。

#インストール
brew install ffmpeg

#MOV形式からのgif変換: 横幅を750にする
ffmpeg -i input.mov -vf scale=750:-1 -r 10 output.gif

参考資料

ladal.edu.au

plotly.com

plotly.com

plotly.com

stackoverflow.com

rstudio.github.io

plotly-r.com