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

まずは、データ分析、コマンドラインのメモとして

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

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

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

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

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

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

f:id:skume:20210220205554g:plain:w400

目次

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

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

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

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

日経平均株価(日経225)

f:id:skume:20210220205608p:plain:w400

ja.wikipedia.org

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

f:id:skume:20210220205614p:plain:w500

ja.wikipedia.org

NASDAQ-100

f:id:skume:20210220205619p:plain:w500

en.wikipedia.org

S&P500

f:id:skume:20210220205623p:plain:w500

en.wikipedia.org

S&P100

f:id:skume:20210220205629p:plain:w350

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パッケージあたりをインストールして準備する。

# Easily Harvest (Scrape) Web Pages
install.packages("rvest")
library(rvest)

# Quantitative Financial Modelling Framework
install.packages("quantmod")
library(quantmod)

# A Forward-Pipe Operator for R
install.packages("magrittr")
library(magrittr)

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

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

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

日経平均株価(日経225)

#Nikkei225
Nikkei225.h <- Nikkei225_url %>%
  read_html() %>%
  html_nodes("table") %>%
  .[4:38] %>%
  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") %>%
  .[[2]] %>%
  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

#ナスダック-100指数
NASDAQ100 <- NASDAQ100_url %>%
  read_html() %>%
  html_nodes("table") %>%
  .[[4]] %>%
  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

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

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年中の値動きを取得して、 アニメーションにしてみる。

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

f:id:skume:20210220205554g:plain:w500

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

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

#NASDAQ100
NASDAQ100 <- NASDAQ100_url %>%
  read_html() %>%
  html_nodes("table") %>%
  .[[4]] %>%
  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

blogs.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年最後に入れ替えがあったのだけど