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

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

【R・ビッグデータ解析の処方箋】readLines、connection オブジェクトを使って、テキストファイルの1行ずつ読み込みを実行してみた件〜

はじめに

現状、数十GB・数百GBといった、大きなファイルを扱う際には、R/メモリ上で全データを読み込むことはややリスキーである。

ファイル全体を読み込まず、ファイル内の1行ずつで処理を実施する工夫が必要となる。*1

Rで、1行ずつの処理を実行するには、readLines関数を用いる。

readLines関数は、connection オブジェクトから一部またはすべてのテキスト行を読み込む関数である。

また、connection オブジェクトとは、つまり「一般化されたファイル」(圧縮ファイル、URL、パイプなど)を作成、オープン、クローズするための関数オブジェクトを指す。このR Documentationの説明を読んでてても、いまいち分からないのだが、要するに、R上に全ファイルのロードせずに、DB的にファイルと接続して、データのやり取りをするというイメージだろう。

テストファイルを用意したので、readLinesの実行例を解説する。

練習ファイルのダウンロード

#gistからファイル・ダウンロード
utils::download.file(url="https://gist.githubusercontent.com/kumeS/398fbeb50c71cf828190aced63b0d1b0/raw/0fb095ae07a4e331ef23e6fc9350a5d7d276b732/file.txt",
                     destfile="file.txt")

#ファイル表示
system("cat file.txt")
#AAA
#BBB
#CCC
#DDD
#EEE
#FFF
#GGG
#HHH
#III
#JJJ
#KKK
#LLL
#MMM
#NNN
#OOO
#PPP
#QQQ
#RRR

readLinesのダメな実行例

これは、間違った使い方であるが、 ファイル名を指定して、readLinesを実行してもダメ・・・である。

以下の実行だと、同じ出力が繰り返されるだけである。

#ファイルパス
txt_file <- "./file.txt"

readLines(con=txt_file, n = 1)
#[1] "AAA"
readLines(con=txt_file, n = 1)
#[1] "AAA"

##引数
#con: connection オブジェクト
#n: 読み込む (最大の) 行数

readLinesの実行コード例

まず、ファイルパスから、connection オブジェクトを作成する。

con_file <- file(description = "./file.txt", open = "r")

str(con_file)
# 'file' int 3
# - attr(*, "conn_id")=<externalptr> 

con_file
#A connection with                        
#description "./file.txt"
#class       "file"      
#mode        "r"         
#text        "text"      
#opened      "opened"    
#can read    "yes"       
#can write   "no"  

connection オブジェクトをreadLinesで読み込んでいくと、実行回数ごとに出力が変わる。

#readLinesを実行するごとに、違う行が表示される
readLines(con_file, n = 1)
#[1] "AAA"
readLines(con_file, n = 1)
#[1] "BBB"
readLines(con_file, n = 1)
#[1] "CCC"
readLines(con_file, n = 1)
#[1] "DDD"
readLines(con_file, n = 1)
#[1] "EEE"

次に、forループで実行する例を示す。

#for実行の場合
con_file <- file(description = "./file.txt", open = "r")
for(n in 1:18){
a <- readLines(con_file, n = 1)
print(a)
}

#[1] "AAA"
#[1] "BBB"
#[1] "CCC"
#[1] "DDD"
#[1] "EEE"
#[1] "FFF"
#[1] "GGG"
#[1] "HHH"
#[1] "III"
#[1] "JJJ"
#[1] "KKK"
#[1] "LLL"
#[1] "MMM"
#[1] "NNN"
#[1] "OOO"
#[1] "PPP"
#[1] "QQQ"
#[1] "RRR"

さらに、stackoverflow内で、dvdさんが示していた関数の事例を下記に示す。

whileを使って、if ( length(line) == 0 )の条件を入れることで、 ファイルの全行数が分からなくても、実行の開始・終了ができる。

processFile = function(filepath) {
  con = file(filepath, "r")
  while ( TRUE ) {
    line = readLines(con, n = 1)
    if ( length(line) == 0 ) {
      break
    }
    print(line)
  }
  close(con)
}

processFile(filepath="./file.txt")
#[1] "AAA"
#[1] "BBB"
#[1] "CCC"
#[1] "DDD"
#[1] "EEE"
#[1] "FFF"
#[1] "GGG"
#[1] "HHH"
#[1] "III"
#[1] "JJJ"
#[1] "KKK"
#[1] "LLL"
#[1] "MMM"
#[1] "NNN"
#[1] "OOO"
#[1] "PPP"
#[1] "QQQ"
#[1] "RRR"


#あるいは、repeat関数 でもOK!!

processFile_r <- function(filepath) {
  con = file(filepath, "r")
  repeat {
    line = readLines(con, n = 1)
    if ( length(line) == 0 ) {
      break
    }
    print(line)
  }
  close(con)
}

まとめ

connection オブジェクトの扱い方とか、ノーマークだったけど、Rにも便利なオブジェクトがあるもんだ。

R・ビッグデータ解析の処方箋 関連記事

skume.net

R言語 お勧め書籍

補足

readLines関数で、10万行の同時読み込み

実際の事例では、readLines関数でGBオーダーのテキストファイルを読み込んでいく場合に、n = 1では、インタプリンタ言語の性格上、非常に読み込み効率が悪く、n = 10000あるいはn = 100000くらいに設定して読み込むのが良い。

私の経験上、readLines関数での10万行の読み込みは、1-2秒で完了する。

#readLinesの実行例
readLines(con_file, n = 100000)

参考資料

stackoverflow.com

*1:sedコマンドで、1行ずつ行を抽出できるが、sedコマンドでも一度ファイル全体を読み込んでから処理を実行しているらしく、大きなファイルにsed実行は不向きである。

Mac版 JAVAバージョン切り替えメモ : Java 14 から 12 への切り替え

Javaパスを切り替えるメモ書き

Mac PC内に、Java 14 と 12 が混在している状況で、Java 14 からJava 12にパスを切り替えるメモ書き。

#現在のJava パス
which java
#/usr/bin/java

# Javaのバージョン確認 => java 14 が使用されている
java -version
#java version "14" 2020-03-17
#Java(TM) SE Runtime Environment (build 14+36-1461)
#Java HotSpot(TM) 64-Bit Server VM (build 14+36-1461, mixed mode, sharing)

#configの確認 => Java 14 と 12が存在する
brew config
#HOMEBREW_VERSION: 2.7.7
#...
#Java: 14, 12.0.2
#macOS: 10.15.7-x86_64
#CLT: 12.0.32.28
#Xcode: 12.3
#XQuartz: 2.7.11 => /opt/X11

# Java VMの確認
/usr/libexec/java_home -V
#Matching Java Virtual Machines (3):
#    14, x86_64:    "Java SE 14" /Library/Java/JavaVirtualMachines/jdk-14.jdk/Contents/Home
#    14, x86_64:    "OpenJDK 14" /Library/Java/JavaVirtualMachines/openjdk-14.jdk/Contents/Home
#    12.0.2, x86_64:  "AdoptOpenJDK 12"    /Library/Java/JavaVirtualMachines/adoptopenjdk-12.jdk/Contents/Home
#
#/Library/Java/JavaVirtualMachines/jdk-14.jdk/Contents/Home

環境変数の設定に関する2パターンの方法

環境変数の設定には、2パターンの方法がある。

  • (1)一時的に環境変数JAVA_HOMEの設定を書き換えるか

  • (2).bash_profileに書き込んで、起動毎に環境変数JAVA_HOMEの設定を行うか

である。

一時的な設定の場合

いちおう、両者のやり方を下記に示す。

## 環境変数JAVA_HOMEの設定
#一時的な設定の場合
cd 
export JAVA_HOME=`/usr/libexec/java_home -v "12"`; PATH=${JAVA_HOME}/bin:${PATH}

一時的な設定の場合

#.bash_profileに環境変数の設定を書き込む場合
cd
echo 'export JAVA_HOME=`/usr/libexec/java_home -v "12"`; PATH=${JAVA_HOME}/bin:${PATH}' >> .bash_profile
source .bash_profile

設定後の確認

#設定の確認
java -version
#openjdk version "12.0.2" 2019-07-16
#OpenJDK Runtime Environment AdoptOpenJDK (build 12.0.2+10)
#OpenJDK 64-Bit Server VM AdoptOpenJDK (build 12.0.2+10, mixed mode)

#パスの確認
which java
#/Library/Java/JavaVirtualMachines/adoptopenjdk-12.jdk/Contents/Home/bin/java

R言語/Webスクレイピングで、Wikipediaページからテーブル情報を取得する 〜日経225、米国ダウ平均株価、S&P500、NASDAQ-100とかの銘柄リストを取得して、株価も見てみた件〜

はじめに

2022年11月21日ウィキペディアページとの整合性のためにスクリプトの一部修正

ずっと纏めたかったけど、後々になっていた件。

R言語を用いた、Webからの銘柄コード取得と株価情報の取得について解説する。

主な内容としては、「Webスクレイピング」によるWikipediaページからの銘柄コード情報の取得、 それとRで株情報を扱う「quantmod パッケージ」を使って、各銘柄情報を収集する内容である。

また、2020年年初から12月末までのNASDAQ-100銘柄*1のパフォーマンスをGIFアニメーションにしてみた。

以下のようなアニメーションを作ります。やはり、テスラ(TSLA)とズーム(ZM)、ペロトン(PTON)、モデルナ(RNA)あたりがキラリと光りますね。

各銘柄リストのWikipediaページ、Rでの下準備

今回は、Wikipediaページから銘柄コードを取得する。

Wikipediaでは、各指数の銘柄リストをテーブル形式にして、まとめてくれている。

具体的に、銘柄リストとURLを見ていくと、以下の通りである。

日経平均株価(日経225)

ja.wikipedia.org

米国ダウ平均株価 30銘柄 (Dow Jones Industrial Average)

ja.wikipedia.org

NASDAQ-100

en.wikipedia.org

S&P500

en.wikipedia.org

S&P100

en.wikipedia.org

下準備として、各URLは、変数に格納しておく。

Nikkei225_url <- "https://ja.wikipedia.org/wiki/%E6%97%A5%E7%B5%8C%E5%B9%B3%E5%9D%87%E6%A0%AA%E4%BE%A1"
#browseURL(Nikkei225_url)

DJIA_url <- "https://ja.wikipedia.org/wiki/%E3%83%80%E3%82%A6%E5%B9%B3%E5%9D%87%E6%A0%AA%E4%BE%A1"
#browseURL(DJIA_url)

NASDAQ100_url <- "https://en.wikipedia.org/wiki/NASDAQ-100"
#browseURL(NASDAQ100_url)

SP500_url <- "https://en.wikipedia.org/wiki/List_of_S%26P_500_companies"
#browseURL(SP500_url)

SP100_url <- "https://en.wikipedia.org/wiki/S%26P_100"
#browseURL(SP100_url)

使用するパッケージの事前準備

主に、rvestquantmodmagrittrパッケージあたりをインストールして準備する。

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

library(rvest)
library(quantmod)
library(magrittr)

Wikipediaページからの銘柄リストの取得

Wikipediaは自由編集なので仕方ないのだが、 それぞれのページで、何番目のテーブルに銘柄コードが記載されているかが変わる。 また、テーブルの形や列名も違うので、それぞれに合わせて取得することになる。

以下に、それぞれの実行コードを示す。

日経平均株価(日経225)

日経225の銘柄リストを取得します。

#Nikkei225
Nikkei225.h <- Nikkei225_url %>%
  read_html() %>%
  html_nodes("table") %>%
  .[6:40] %>%
  html_table()

#リスト表示
head(Nikkei225.h)

#[[1]]
#   証券コード                           銘柄 備考
#1        2002           日清製粉グループ本社   NA
#2        2269           明治ホールディングス   NA
#3        2282                       日本ハム   NA
#4        2501       サッポロホールディングス   NA
#5        2502 アサヒグループホールディングス   NA
#6        2503         キリンホールディングス   NA
#7        2531             宝ホールディングス   NA
#8        2801                   キッコーマン   NA
#9        2802                         味の素   NA
#10       2871                       ニチレイ   NA
#11       2914                 日本たばこ産業   NA
#
#[[2]]
#  証券コード     銘柄 備考
#1       3101   東洋紡   NA
#2       3103 ユニチカ   NA
#3       3401     帝人   NA
#4       3402     東レ   NA

#リストデータをデータフレームへ変換
Nikkei225 <- c()
for(n in 1:length(Nikkei225.h)){
 Nikkei225 <- Nikkei225 %>%  rbind(Nikkei225.h[[n]])
}

#表示
head(Nikkei225)
#  証券コード                           銘柄 備考
#1       2002           日清製粉グループ本社   NA
#2       2269           明治ホールディングス   NA
#3       2282                       日本ハム   NA
#4       2501       サッポロホールディングス   NA
#5       2502 アサヒグループホールディングス   NA
#6       2503         キリンホールディングス   NA

Nikkei225$証券コード
#  [1] 2002 2269 2282 2501 2502 2503 2531 2801 2802 2871 2914 3101 3103 3401
# [15] 3402 3861 3863 3405 3407 4004 4005 4021 4042 4043 4061 4063 4183 4188
# [29] 4208 4452 4631 4901 4911 6988 4151 4502 4503 4506 4507 4519 4523 4568
# [43] 4578 5019 5020 5101 5108 5201 5202 5214 5232 5233 5301 5332 5333 5401
# [57] 5406 5411 5541 3436 5703 5706 5707 5711 5713 5714 5801 5802 5803 5901
# [71] 5631 6103 6113 6301 6302 6305 6326 6361 6367 6471 6472 6473 7004 7011
# [85] 7013 3105 6479 6501 6503 6504 6506 6645 6674 6701 6702 6703 6724 6752
# [99] 6753 6758 6762 6770 6841 6857 6902 6952 6954 6971 6976 7735 7751 7752
#[113] 8035 7003 7012 7201 7202 7203 7205 7211 7261 7267 7269 7270 7272 4543
#[127] 4902 7731 7733 7762 7832 7911 7912 7951 1332 1333 1605 1721 1801 1802
#[141] 1803 1808 1812 1925 1928 1963 2768 8001 8002 8015 8031 8053 8058 3086
#[155] 3099 3382 8233 8252 8267 9983 7186 8303 8304 8306 8308 8309 8316 8331
#[169] 8354 8355 8411 8601 8604 8628 8630 8725 8750 8766 8795 8253 8697 3289
#[183] 8801 8802 8804 8830 9001 9005 9007 9008 9009 9020 9021 9022 9062 9064
#[197] 9101 9104 9107 9202 9301 9412 9432 9433 9434 9613 9984 9501 9502 9503
#[211] 9531 9532 2413 2432 3659 4324 4689 4704 4751 4755 6098 6178 9602 9735
#[225] 9766

米国ダウ平均株価 30銘柄 (Dow Jones Industrial Average)

米国ダウ平均株価の銘柄リストを取得します。

#ダウ平均株価(Dow Jones Industrial Average)
DJIA <- DJIA_url %>%
  read_html() %>%
  html_nodes("table") %>%
  .[[1]] %>%
  html_table

head(DJIA)
#  No シンボル                                           企業名         業種        採用日 上場市場
#1  1     AAPL                               Apple Inc.アップル コンピュータ 2015年3月19日   NASDAQ
#2  2     AMGN                             Amgen Inc.アムジェン       医薬品 2020年8月31日   NASDAQ
#3  3      AXP     American Express Co.アメリカン・エキスプレス         金融 1982年8月30日     NYSE
#4  4       BA                             Boeing Co.ボーイング       航空機 1987年3月12日     NYSE
#5  5      CAT                     Caterpillar Inc.キャタピラー         重機  1991年5月6日     NYSE
#6  6      CRM Salesforce.com, Inc.セールスフォース・ドットコム ソフトウェア 2020年8月31日     NYSE

DJIA$シンボル
# [1] "AAPL" "AMGN" "AXP"  "BA"   "CAT"  "CRM"  "CSCO" "CVX"  "DIS"  "DOW" 
#[11] "GS"   "HD"   "HON"  "IBM"  "INTC" "JNJ"  "JPM"  "KO"   "MCD"  "MMM" 
#[21] "MRK"  "MSFT" "NKE"  "PG"   "TRV"  "UNH"  "V"    "VZ"   "WBA"  "WMT" 

NASDAQ-100

次に、NASDAQ-100の銘柄リストを取得します。

#ナスダック-100指数
NASDAQ100 <- NASDAQ100_url %>%
  read_html() %>%
  html_nodes("table") %>%
  .[[5]] %>%
  html_table()

head(NASDAQ100)
#                  Company Ticker            GICS Sector              GICS Sub-Industry
#1     Activision Blizzard   ATVI Communication Services Interactive Home Entertainment
#2              Adobe Inc.   ADBE Information Technology           Application Software
#3  Advanced Micro Devices    AMD Information Technology                 Semiconductors
#4 Alexion Pharmaceuticals   ALXN            Health Care                Pharmaceuticals
#5        Align Technology   ALGN            Health Care           Health Care Supplies
#6 Alphabet Inc. (Class A)  GOOGL Communication Services   Interactive Media & Services

NASDAQ100$Ticker
# [1] "ATVI"  "ADBE"  "AMD"   "ALXN"  "ALGN"  "GOOGL" "GOOG"  "AMZN"  "AEP"   "AMGN"  "ADI"   "ANSS"  "AAPL" 
#[14] "AMAT"  "ASML"  "TEAM"  "ADSK"  "ADP"   "BIDU"  "BIIB"  "BKNG"  "AVGO"  "CDNS"  "CDW"   "CERN"  "CHTR" 
#[27] "CHKP"  "CTAS"  "CSCO"  "CTSH"  "CMCSA" "CPRT"  "COST"  "CSX"   "DXCM"  "DOCU"  "DLTR"  "EBAY"  "EA"   
#[40] "EXC"   "FB"    "FAST"  "FISV"  "FOXA"  "FOX"   "GILD"  "IDXX"  "ILMN"  "INCY"  "INTC"  "INTU"  "ISRG" 
#[53] "JD"    "KDP"   "KLAC"  "KHC"   "LRCX"  "LULU"  "MAR"   "MRVL"  "MTCH"  "MXIM"  "MELI"  "MCHP"  "MU"   
#[66] "MSFT"  "MRNA"  "MDLZ"  "MNST"  "NTES"  "NFLX"  "NVDA"  "NXPI"  "ORLY"  "OKTA"  "PCAR"  "PAYX"  "PYPL" 
#[79] "PTON"  "PEP"   "PDD"   "QCOM"  "REGN"  "ROST"  "SGEN"  "SIRI"  "SWKS"  "SPLK"  "SBUX"  "SNPS"  "TMUS" 
#[92] "TSLA"  "TXN"   "TCOM"  "VRSN"  "VRSK"  "VRTX"  "WBA"   "WDAY"  "XEL"   "XLNX"  "ZM"   

S&P500

次に、S&P500の銘柄リストを取得します。

SP500 <- SP500_url %>%
  read_html() %>%
  html_nodes("table") %>%
  .[[1]] %>%
  html_table()

head(SP500)
#  Symbol            Security SEC filings            GICS Sector              GICS Sub-Industry
#1    MMM          3M Company     reports            Industrials       Industrial Conglomerates
#2    ABT Abbott Laboratories     reports            Health Care          Health Care Equipment
#3   ABBV         AbbVie Inc.     reports            Health Care                Pharmaceuticals
#4   ABMD             Abiomed     reports            Health Care          Health Care Equipment
#5    ACN           Accenture     reports Information Technology IT Consulting & Other Services
#6   ATVI Activision Blizzard     reports Communication Services Interactive Home Entertainment
#     Headquarters Location Date first added     CIK     Founded
#1      St. Paul, Minnesota       1976-08-09   66740        1902
#2  North Chicago, Illinois       1964-03-31    1800        1888
#3  North Chicago, Illinois       2012-12-31 1551152 2013 (1888)
#4   Danvers, Massachusetts       2018-05-31  815094        1981
#5          Dublin, Ireland       2011-07-06 1467373        1989
#6 Santa Monica, California       2015-08-31  718877        2008

head(SP500$Symbol)
#[1] "MMM"  "ABT"  "ABBV" "ABMD" "ACN"  "ATVI"

S&P100

次に、S&P100の銘柄リストを取得します。

sp100 <- SP100_url %>%
  read_html() %>%
  html_nodes("table") %>%
  .[[3]] %>%
  html_table()

head(sp100)
#  Symbol                         Name
#1   AAPL                   Apple Inc.
#2   ABBV                  AbbVie Inc.
#3    ABT          Abbott Laboratories
#4    ACN                    Accenture
#5   ADBE                   Adobe Inc.
#6    AIG American International Group

head(sp100$Symbol)
#[1] "AAPL" "ABBV" "ABT"  "ACN"  "ADBE" "AIG" 

NASDAQ-100銘柄のパフォーマンスGIFアニメーション

NASDAQ-100銘柄の2020年中の値動きを取得して、 アニメーションにしてみる。

出来上がりは以下のような感じである(再掲載)。

それでは、さっそく、実行コードを書いてみる。

まずは、2020年中のNASDAQ-100銘柄の値動きをすべて取得してみる。

#NASDAQ100
NASDAQ100 <- NASDAQ100_url %>%
  read_html() %>%
  html_nodes("table") %>%
  .[[5]] %>%
  html_table()

nasdaq100.tic <- NASDAQ100$Ticker
nasdaq100.tic
#  [1] "ATVI"  "ADBE"  "AMD"   "ALXN"  "ALGN"  "GOOGL" "GOOG"  "AMZN" 
#  [9] "AEP"   "AMGN"  "ADI"   "ANSS"  "AAPL"  "AMAT"  "ASML"  "TEAM" 
# [17] "ADSK"  "ADP"   "BIDU"  "BIIB"  "BKNG"  "AVGO"  "CDNS"  "CDW"  
# [25] "CERN"  "CHTR"  "CHKP"  "CTAS"  "CSCO"  "CTSH"  "CMCSA" "CPRT" 
# [33] "COST"  "CSX"   "DXCM"  "DOCU"  "DLTR"  "EBAY"  "EA"    "EXC"  
# [41] "FB"    "FAST"  "FISV"  "FOXA"  "FOX"   "GILD"  "IDXX"  "ILMN" 
# [49] "INCY"  "INTC"  "INTU"  "ISRG"  "JD"    "KDP"   "KLAC"  "KHC"  
# [57] "LRCX"  "LULU"  "MAR"   "MRVL"  "MTCH"  "MXIM"  "MELI"  "MCHP" 
# [65] "MU"    "MSFT"  "MRNA"  "MDLZ"  "MNST"  "NTES"  "NFLX"  "NVDA" 
# [73] "NXPI"  "ORLY"  "OKTA"  "PCAR"  "PAYX"  "PYPL"  "PTON"  "PEP"  
# [81] "PDD"   "QCOM"  "REGN"  "ROST"  "SGEN"  "SIRI"  "SWKS"  "SPLK" 
# [89] "SBUX"  "SNPS"  "TMUS"  "TSLA"  "TXN"   "TCOM"  "VRSN"  "VRSK" 
# [97] "VRTX"  "WBA"   "WDAY"  "XEL"   "XLNX"  "ZM"  

#2020年中の株価取得
Date <- c("2020-01-01", "2020-12-31")
list <- as.character(unlist(nasdaq100.tic))
quantmod::getSymbols(list, src = "yahoo", verbose = T, from = Date[1], to=Date[2])

#空のデータフレームの作成
stock <- data.frame(matrix(NA, nrow=dim(GOOGL)[1], ncol=length(list)))
colnames(stock) <- list

head(stock)
#  ATVI ADBE AMD ALXN ALGN GOOGL GOOG AMZN AEP AMGN ADI ANSS AAPL AMAT
#1   NA   NA  NA   NA   NA    NA   NA   NA  NA   NA  NA   NA   NA   NA
#2   NA   NA  NA   NA   NA    NA   NA   NA  NA   NA  NA   NA   NA   NA
#3   NA   NA  NA   NA   NA    NA   NA   NA  NA   NA  NA   NA   NA   NA
#4   NA   NA  NA   NA   NA    NA   NA   NA  NA   NA  NA   NA   NA   NA
#5   NA   NA  NA   NA   NA    NA   NA   NA  NA   NA  NA   NA   NA   NA
#6   NA   NA  NA   NA   NA    NA   NA   NA  NA   NA  NA   NA   NA   NA

#データの代入
#文字列(ex.  "assign('a', ATVI[,4])" )を作成して、
#eval(parse(text = "..."))で、その文字列を命令文として実行する
for(n in seq_len(length(list))){
try(eval(parse(text = paste("assign('a', ", list[n], "[,4])", sep=""))))
stock[,n] <- a
}

#行名を日付にする
rownames(stock) <- rownames(data.frame(a))

#データ取得完了
head(stock)
#            ATVI   ADBE   AMD   ALXN   ALGN   GOOGL    GOOG    AMZN
#2020-01-02 58.65 334.43 49.10 107.84 283.68 1368.68 1367.37 1898.01
#2020-01-03 58.67 331.81 48.60 106.41 280.44 1361.52 1360.66 1874.97
#2020-01-06 59.74 333.71 48.39 106.58 285.88 1397.81 1394.21 1902.88
#2020-01-07 60.34 333.39 48.25 106.85 283.06 1395.11 1393.34 1906.86
#2020-01-08 59.88 337.87 47.83 108.58 286.00 1405.04 1404.32 1891.97
#2020-01-09 59.34 340.45 48.97 110.74 296.54 1419.79 1419.83 1901.05

次に、年初時の株価を 100 に補正して、アニメーション用にデータの加工をしてみる。

#年初時の株価を 100 に補正
stock.c <- stock
for(n in 1:ncol(stock)){
stock.c[,n] <- as.numeric(stock[,n])/as.numeric(stock[1,n])*100  
}

head(stock.c)
#               ATVI      ADBE       AMD      ALXN      ALGN     GOOGL
#2020-01-02 100.0000 100.00000 100.00000 100.00000 100.00000 100.00000
#2020-01-03 100.0341  99.21658  98.98167  98.67397  98.85787  99.47687
#2020-01-06 101.8585  99.78471  98.55397  98.83161 100.77553 102.12833
#2020-01-07 102.8815  99.68903  98.26884  99.08198  99.78145 101.93105
#2020-01-08 102.0972 101.02862  97.41345 100.68621 100.81783 102.65657
#2020-01-09 101.1765 101.80008  99.73524 102.68917 104.53328 103.73425

#データの行列を入れ替える
stock.t <- t(stock.c)
head(stock.t)

stock01 <- data.frame(tic=rownames(stock.t), Sector=NASDAQ100$"GICS Sector", stock.t)
rownames(stock01) <- 1:nrow(stock01)
head(stock01)

#   tic                 Sector X2020.01.02 X2020.01.03 X2020.01.06
#1 ATVI Communication Services         100   100.03409   101.85848
#2 ADBE Information Technology         100    99.21658    99.78471
#3  AMD Information Technology         100    98.98167    98.55397
#  X2020.01.07 X2020.01.08 X2020.01.09 X2020.01.10 X2020.01.13
#1   102.88150   102.09718   101.17647   100.51151   101.00597
#2    99.68903   101.02862   101.80008   101.60871   103.34899
#3    98.26884    97.41345    99.73524    98.10591    99.28717

install.packages("tidyr")
library(tidyr)

#少し間引く
stock02 <- stock01[,c(1:2, seq(3, ncol(stock01), by=5))]

#データの並びを変える
stock03 <- gather(stock02, key="date", value="close", -c(tic, Sector)) 
stock03$date <- sub("X", "", stock03$date)
stock03$date <- gsub("\\.", "/", stock03$date)
stock03$date <- paste0(stock03$date, "-16-00-00")

head(stock03)
#    tic                 Sector                date close
#1  ATVI Communication Services 2020/01/02-16-00-00   100
#2  ADBE Information Technology 2020/01/02-16-00-00   100
#3   AMD Information Technology 2020/01/02-16-00-00   100
#4  ALXN            Health Care 2020/01/02-16-00-00   100
#5  ALGN            Health Care 2020/01/02-16-00-00   100
#6 GOOGL Communication Services 2020/01/02-16-00-00   100

ここで、stock03のデータを使って、アニメーションを作成してみる。

#必要なパッケージの準備
install.packages("ggplot2")
library(ggplot2)

install.packages("treemapify")
library(treemapify)

install.packages("gganimate")
library(gganimate)

install.packages("gapminder")
library(gapminder)

install.packages("gifski")
library(gifski)

#日時列に変える
stock03$date  <- as.Date(stock03$date)

#株価の変動幅から、カラーを決める
head(stock03)
stock03$dclose <- stock03$close - 100
stock03$dclose2 <- NA
colfunc <- grDevices::colorRampPalette(c("brown3", "white", "darkgreen"))
a <- colfunc(18)
b1 <- seq(-50, 0, length.out=9)
b2 <- seq(0, 250, length.out=9)
b3 <- c(b1, b2[-1], 750)

for(n in length(b3):1){
stock03$dclose2[stock03$dclose < b3[n]] <- a[n]  
}

head(stock03)
#    tic                 Sector       date close dclose dclose2
#1  ATVI Communication Services 2020-01-02   100      0 #F0F5F0
#2  ADBE Information Technology 2020-01-02   100      0 #F0F5F0
#3   AMD Information Technology 2020-01-02   100      0 #F0F5F0
#4  ALXN            Health Care 2020-01-02   100      0 #F0F5F0
#5  ALGN            Health Care 2020-01-02   100      0 #F0F5F0
#6 GOOGL Communication Services 2020-01-02   100      0 #F0F5F0

#ツリーマップの作成
p <- ggplot(stock03, aes(label=tic, area = close, 
            fill = dclose2, subgroup = Sector )) +
  geom_treemap( layout = "squarified", colour="white", start="topleft") +
  scale_fill_identity() +
  geom_treemap_subgroup_border(layout = "squarified", colour = "white", size = 5, start="topleft") +
  geom_treemap_subgroup_text(layout = "squarified", place = "top",
                             grow = T, alpha = 1, colour = "#FAFAFA",
                             min.size = 0, start = "topleft") +
  geom_treemap_text(layout = "squarified", place = "centre", grow = TRUE, 
                    colour = "grey50", min.size = 8, reflow = T, start = "topleft") +
  transition_time(date) +
  labs(title = "NASDAQ-100, Date: {frame_time}") +
  ease_aes('linear')

#アニメーションとして出力(2-3分くらいかかる)
animate(p, duration = 25, width = 500, height = 500, renderer = gifski_renderer("NASDAQ100_animation.gif"))

まとめ

株価コード取得から、株価変動のアニメーション作成までを紹介した。

1つ1つの作業はそんなだけど、全体を通してやると結構面倒な感じがする。

あと、gganimateは、なかなか良さそうなので、また別の企画でも使ってみたい。

補足

これは参考までに、BatchGetSymbolsパッケージの関数でも、 S&P500の銘柄リストが取得できる。 結局、上記とほぼ同じことが実装されている。

#Downloads and Organizes Financial Data for Multiple Tickers
install.packages("BatchGetSymbols")
library(BatchGetSymbols)

#S&P500のティッカーの取得
sp500 <- GetSP500Stocks()

head(sp500)
#  Tickers             Company SEC.filings            GICS.Sector              GICS.Sub.Industry
#1     MMM          3M Company     reports            Industrials       Industrial Conglomerates
#2     ABT Abbott Laboratories     reports            Health Care          Health Care Equipment
#3    ABBV         AbbVie Inc.     reports            Health Care                Pharmaceuticals
#4    ABMD             Abiomed     reports            Health Care          Health Care Equipment
#5     ACN           Accenture     reports Information Technology IT Consulting & Other Services
#6    ATVI Activision Blizzard     reports Communication Services Interactive Home Entertainment
#               HQ.Location Date.First.Added     CIK     Founded
#1      St. Paul, Minnesota       1976-08-09   66740        1902
#2  North Chicago, Illinois       1964-03-31    1800        1888
#3  North Chicago, Illinois       2012-12-31 1551152 2013 (1888)
#4   Danvers, Massachusetts       2018-05-31  815094        1981
#5          Dublin, Ireland       2011-07-06 1467373        1989
#6 Santa Monica, California       2015-08-31  718877        2008

head(sp500$Tickers)
#[1] "MMM"  "ABT"  "ABBV" "ABMD" "ACN"  "ATVI"

参考資料

cran.r-project.org

stackoverflow.com

gist.github.com

stackoverflow.com

Downloading S&amp;P 500 Stock Data from Google/Quandl with R (Command Line&nbsp;Script)ntguardian.wordpress.com

towardsdatascience.com

https://blogs.oracle.com/datascience/performing-a-time-series-analysis-on-the-sandp-500-stock-indexblogs.oracle.com

https://github.com/rstudio/cheatsheets/raw/master/data-import.pdfgithub.com

https://evoldyn.gitlab.io/evomics-2018/ref-sheets/R_data-transformation.pdfevoldyn.gitlab.io

*1:実際、2020年最後に入れ替えがあったのだけど