データとバスケ」カテゴリーアーカイブ

2日連続のゲームは選手のパフォーマンスにどう影響しているのか

ご存知の通りBリーグでは土日(たまに金土もしくは日月)に渡って2日連続で同じチーム同士が対戦するスケジュールが基本です。私はバスケットボール選手ではないので実感はできませんが、これはなかなかに選手の負担が大きそうです。プレータイムが長ければ尚更です。

私はBリーグ以外のプロバスケットリーグをあまり知りませんが、今シーズンにオーストラリアのNBLを観ていた限りでは、2日間連続のゲームどころか中1日や中2日もそんなになかったように思います(年末などには中1日があったと思います。)

Bリーグがこのスケジュールになっている理由は色々あるでしょうし、私はそれに賛成も反対も述べる気はないのですが、もしBリーグに独特なものであれば分析しない手はないと思いました。またいつも通りデータを見てみたいと思います。

ここではB1、B2の過去3レギュラーシーズンすべてのゲーム(2018-19シーズンは38試合終了時点)から、2日連続で同じチーム同士が対戦したゲームだけ抽出し(ちなみに2,622ゲームありました)、それをゲーム1とゲーム2に分けて比べてみたいと思います。

得点

まずは得点を見てみましょう。ゲーム2ではシュートが入らなくてロースコアになったり、逆にディフェンスが雑になってハイスコアになってしまうような傾向があるでしょうか。シーズンごとに全体の傾向を見てみましょう。

f:id:rintaromasuda:20190210000331j:plain

全体的にはあまり傾向に違いはないようです。チーム別だとどうでしょうか。2018-19シーズンのB1各チームのデータを見てみましょう(図が小さくてすみません。)

f:id:rintaromasuda:20190210003006j:plain

基本的には無視できる程度の違いが多いですが、特色のあるチームもあります。例えばシーホース三河や琉球ゴールデンキングスはハイスコアを出したときはほぼゲーム1だったようです。

また京都ハンナリーズや横浜ビー・コルセアーズはゲーム2のほうが得点が安定する傾向が見られます。新潟アルビレックスBBはゲーム1のほうが安定していますね。色々と面白いです。

eFG%

同じ要領で全体のeFG%(スリーポイントに1.5倍のボーナスを与えたFG%)を見てみましょう。ゲーム2だとシュートの確率が悪くなったりしていますでしょうか。

f:id:rintaromasuda:20190210003140j:plain

こちらも全体傾向では意味のある違いはないようです。チーム別だとどうでしょうか。再び2018-19シーズンのB1で見てみましょう。

f:id:rintaromasuda:20190210004212j:plain

サンロッカーズ渋谷、滋賀レイクスターズ、京都ハンナリーズあたりはゲーム2で確率を上げてきています。修正による向上なのか、それともゲーム1ではエンジンがかからないのかは分かりませんが、面白いです。

琉球ゴールデンキングスはゲーム2での落差がかなりありますね。今まで同チームのゲームを観ていて気が付きませんでしたが、ゲーム2ではなかなか得点に苦労していると思われます。

ポゼッション(または試合のペース)

ゲーム2だとみんな疲れているかもしれません。そうするとゲームのペースが遅くなりがちかもしれません。ポゼッション数もゲーム1とゲーム2で比べてみましょう。

なおこのポゼッション数はオリバー式で求めている近似値で、基本的にはシュートの数とターンオーバーの数からオフェンスリバウンドの数を引いたものだと思ってください。

f:id:rintaromasuda:20190210004938j:plain

おっとこれは!意味があるほど大きい差かどうかは議論の余地がありますが、少なくても3シーズンで同じ傾向にあります。ゲーム2の方がペースが遅いのでしょうか。チーム別ではどうでしょう。

f:id:rintaromasuda:20190210005516j:plain

全体傾向がそうなので当たり前ですが、多くのチームでゲーム2ではポゼッション数が減少する傾向にあるようです。トランジションオフェンスが出なくなるのか、シュートへの積極性が低くなるのか、色々と可能性は考えらそうです。

シーホース三河はポゼッション数のゲーム2での減少も面白いのですが、ポゼッション数が他のチームに比べて安定しているのも面白いですね。ハーフコートオフェンスが中心だからでしょうか。

ファウル数

同じ要領でファウル数も見てみましょう。ゲーム2では足が動かず、結果として手を出してファウルが多くなってしまうかもしれません。

f:id:rintaromasuda:20190210070815j:plain

f:id:rintaromasuda:20190210070827j:plain

こちらも全体的にゲーム2で増加傾向があるように見えます。滋賀レイクスターズや富山グラウジーズではかなりその傾向が顕著ですね。滋賀の場合は主力のラワルのファウルトラブルに苦しむケースが多いようですが、もしかしたらゲーム2でそれが起こりがちなのかもしれません。

まあもちろんファウルが多いから悪いと単純に言える話ではなく、秋田ノーザンハピネッツのようにむしろディフェンスのインテンシティが高いからファウル数が多いというケースもあります。

まとめ

いくらでも深掘りできそうなトピックなのですが、とりえあず長くなってきたのでここまでとしたいと思います。もっとディフェンス寄りのスタッツを見ても面白そうですし、選手の運動量などのいわゆるスタッツを超えるデータがあればさらに面白い結果が見られそうです。

B1のチームだけ図に入れてしまったので、B2のチーム別の図は後でTwitterにでも上げようと思います。

追記1

得失点の図をこちらに貼っておきます。

f:id:rintaromasuda:20190211231021j:plain

追記2

B2版の図をこちらに貼っておきます。

f:id:rintaromasuda:20190211231227j:plain

f:id:rintaromasuda:20190211231427j:plain

f:id:rintaromasuda:20190211231444j:plain

f:id:rintaromasuda:20190211231532j:plain

f:id:rintaromasuda:20190211231545j:plain

サンプルコード

この記事に出てくる図を書いたときのコードがこちらにアップロードされています。

ここまでの観客動員数の累計を過去のシーズンと比べてみる

観客動員数の小ネタです。

Bリーグは観客動員数のゴールを(2020年まで?)年平均成長率10%に設定しているそうですが、今シーズンの観客動員数はここまでどうでしょうか?見てみましょう。

f:id:rintaromasuda:20190208002709j:plain

ご覧の通り今シーズンの序盤は躓いたものの、昨シーズンの同時期と比べて今シーズンが徐々に離しつつあります。これ自体は素晴らしいです。

しかし図からもわかると思いますが、昨季までは1月の頭に長めの空白期間がありました。そして今季はその埋め合わせをするかのように、B1にはFIBAワールドカップアジア予選Window6に向けた空白期間が2月に設定されています。

このB1の空白期間にB2がどこまで頑張れるか、そしてB1が再開してからのシーズン終盤にリーグを盛り上げ、どこまで客足を伸ばせるのかが10%成長達成の為の鍵となりそうです。

B2の観客動員数と言えば、今シーズン戦績は絶好調である群馬クレインサンダーズが、観客動員数が昇格の規定である平均1,500人(でしたっけ?)に達成しない可能性があり話題になっています。

個人的にはB1に上がるためにはチームがもちろん強くなくてはならない、そして観客動員数というビジネスのゴールも達成していなければならない、というのは少し厳し過ぎるのかな、という印象はあるのですが、規定である以上はクリアしなくてはなりませんね。頑張ってほしいところです。

安藤周人はスリーポイントのBリーグ記録を更新するか

名古屋ダイヤモンドドルフィンズの安藤周人が今シーズン好調です。スリーポイントの成功数で現在リーグトップを走っており(確率では6位)、推移を見てみると2位以下をかなり離す独走状態となっています。

下の図は現時点のスリーポイント成功数ベスト5の選手の推移を表したものです。選手名の横の%は現時点でのスリーポイント成功率です。8ゲーム目くらいから一気に安藤が飛び出しています。

f:id:rintaromasuda:20190205095913j:plain

実はここまであまり名古屋のゲームを観ていなかったのですが、この間の富山グラウジーズとの2連戦を観た限りではスリーポイントだけの選手では決してなく、鋭いドライブからのペイントタッチも出来る選手ですね。

すごく良く言ってしまうと、青山学院大学の先輩である辻と比江島の両方のプレーが出来るような選手だという印象で、日本代表の合宿にも今後はコンスタントに呼ばれそうですし、非常に楽しみな選手となってきました。

さてスリーポイントの成功数と言えば、2016-17シーズンはマブンガの153本が、2017-18は辻の145本がそれぞれ最高記録でしたが、ここまで安藤はそれらの記録を上回る可能性のあるペースでスリーポイントを決めています

f:id:rintaromasuda:20190205100520j:plain

過去の記録からすると1試合に2.5本のペースでスリーポイントを決めることが出来ればシーズンチャンピオンになることができそうですが、記録の更新を狙うのであれば試合平均で3本近くを狙いたいところです。

安藤はここまで平均出場時間も約30分とタフなシーズンを戦っていますが、是非ともこのままどんどんスリーポイントを狙ってもらい、スリーポイント成功数の記録の更新、そして日本人得点王も狙って欲しいと思います。

NBAのデータAPIを試してみた

このブログではBリーグ以外の話を扱うつもりはないですが、NBAのデータAPIで遊んでみたのでそれの共有です。興味のある方もいるかもしれないと思いましたので。

ちなみに私も最初はNBAのデータを使ってブログを書こうかなと思ったりしたのですが、NBAだと似たようなことをやっている人が既にいっぱいいそうだと思ったのと、やはり愛着(愛情?)という面でBリーグ以上の気持ちがNBAに持てなかったので今に至っています。

ただやはりNBAだとAPIがあったりするので便利ですね。そんなに使いやすいAPIだという印象は持ちませんでしたが(ドキュメントもあまりなさそうです)、それでもほぼリアルタイムで最新の情報が手に入るのは素晴らしいことです。

以下のRのコードはここのドキュメント群を参考にして書いたもので、ゴールデンステート・ウォリアーズ各選手の今季のスタッツを取得し、そしてこのブログで前にやりました出場時間のヒートマップを作成しています。各チームのTeam IDはこちらで分かります。

if (!require(dplyr)) {
install.packages("dplyr")
library(dplyr)
}
if (!require(ggplot2)) {
install.packages("ggplot2")
library(ggplot2)
}
if (!require(stringr)) {
install.packages("stringr")
library(stringr)
}
if(!require(httr)) {
install.packages("httr")
library(httr)
}
if(!require(jsonlite)) {
install.packages("jsonlite")
library(jsonlite)
}
teamId <- 1610612744
# Get game log (a.k.a. schedule) to get Game IDs
url <- paste0("https://stats.nba.com/stats/teamgamelog",
"?DateFrom=&DateTo=&LeagueID=&Season=2018-19&SeasonType=Regular+Season",
"&TeamID=",
as.character(teamId))
httpResponse = GET(url, add_headers(Referer = "http://stats.nba.com"), accept_json())
res <- content(httpResponse)
colNames <- res$resultSets[[1]]$headers
numGames <- length(res$resultSets[[1]]$rowSet)
df.games <- data.frame()
for (i in 1:numGames) {
arrayRow <- as.character(res$resultSets[[1]]$rowSet[[i]])
df <- as.data.frame(matrix(arrayRow, nrow = 1),
stringsAsFactors = FALSE)
colnames(df) <- colNames
df.games <- rbind(df.games, df)
}
# Add game index
df.games$Game_ID <- as.character(df.games$Game_ID)
df.games <- df.games %>%
arrange(Game_ID) %>%
mutate(Game_Index = row_number())
# Access each game
df.boxscore <- data.frame()
for (gameId in df.games$Game_ID) {
url <- paste0("https://stats.nba.com/stats/boxscoretraditionalv2",
"?EndPeriod=1&EndRange=0",
"&GameID=",
gameId,
"&RangeType=0&StartPeriod=1&StartRange=0")
httpResponse = GET(url, add_headers(Referer = "http://stats.nba.com"), accept_json())
res <- content(httpResponse)
colNames <- res$resultSets[[1]]$headers
for (i in 1:length(res$resultSets[[1]]$rowSet)) {
arrayRow <- as.character(res$resultSets[[1]]$rowSet[[i]])
df <- as.data.frame(matrix(arrayRow, nrow = 1),
stringsAsFactors = FALSE)
colnames(df) <- colNames
df.boxscore <- rbind(df.boxscore, df)
}
}
df.output <- merge(df.boxscore,
df.games[, c("Game_ID", "Team_ID", "Game_Index")],
by.x = c("GAME_ID", "TEAM_ID"),
by.y = c("Game_ID", "Team_ID"))
ConvertMinStrToDec <- function(min_str) {
Convert <- function(item) {
min <- as.numeric(item[1])
min <- min + as.numeric(item[2]) / 60
round(min, 2)
}
ls <- sapply(stringr::str_split(min_str, ":"), Convert)
return(ls)
}
df.output$MIN_NUM <- ConvertMinStrToDec(df.output$MIN)
df.output[is.na(df.output$MIN_NUM),]$MIN_NUM <- 0
ggplot() +
geom_tile(data = df.output,
aes(x = Game_Index,
y = PLAYER_NAME,
fill = MIN_NUM)) +
ylab("") +
xlab("nth Game") +
ggtitle("Miniutes Played over Games - Golden State Warriors") +
scale_fill_continuous(high = "navy", low = "white", guide_legend(title = "MIN")) +
scale_x_continuous(breaks = seq(5, 82, by = 5)) +
theme(plot.background = element_blank(),
plot.title = element_text(hjust = 0.5),
panel.grid.minor = element_blank(),
panel.grid.major = element_blank(),
panel.background = element_blank(),
axis.line = element_blank(),
axis.ticks = element_blank(),
axis.text.y = element_text(hjust = 1, size = 8),
axis.text.x = element_text(size = 8),
strip.text = element_text(face = "bold"),
strip.background = element_rect(fill = "white", colour = "white")
)

結果は以下のようなヒートマップになりました。ロスターの人数は多めのNBAですが、長いシーズン、やはりみんな起用されているのですね。カズンズのプレータイムは今後どうなっていきますかね~。

f:id:rintaromasuda:20190202063222j:plain

今後BリーグがこのようなAPIの作成に着手するかは分かりませんが、それなりの投資になりますし、想像するに優先順位は低めの案件でしょうね。

私は純粋なソフトウェアエンジニア的視点で、APIなどを開放することによりサードパーティーの参加を促しエコシステムを強化する、という戦略の信奉者なので期待したいところではありますが。

追記

過去のデータも取得できることがわかったので、ついでに前人未到の72勝を記録したときのシカゴ・ブルズのヒートマップも作ってみました。マイケル・ジョーダンは全試合出場していました。

f:id:rintaromasuda:20190203075110j:plain

追記(2019.12.13)

NBA APIの仕様が変わり、元のコードだとAPIのアクセスがブロックされるようになりましたのコードを修正しました。

選手の起用状況をヒートマップで把握する(B2版)

ひとつ前の記事で今シーズンのB1各チームがどのように選手を起用しているか、ヒートマップで可視化しました。

この記事では引き続き、今季のB2各チームについて選手の起用状況を可視化したいと思います。こちらも31ゲーム終了時点までです。

東地区

f:id:rintaromasuda:20190130232008j:plain

茨城ロボッツはラマートとバプテストをきれいに交互に起用していますね。これは機械的にこのようなローテーションにしているのか、それとも何かの事情があってのものかは知りませんが、結構めずらしいパターンです。

各チームともやはり外国籍選手のプレータイムは長めになっているようですが、福島ファイヤーボンズはそれを少し分散させている様子です。日本人選手の起用もかなり万遍ない感じの全員バスケットなチームなんですね。

中地区

f:id:rintaromasuda:20190130232022j:plain

まずは八王子ビートレインズですが、シーズン序盤に怪我をはじめとして色々あった為、この図がかなりすごいことになってしまっています。ゲーム中に5人にプレイヤーが満たなくなったりとプロのチームとしての試練もありましたが、この図を見るとそういう時期は抜けたようなので頑張って欲しいですね。

アースフレンズ東京Zは27、28ゲームくらいからかなり起用の様子が変化していますね。同チームの状況をまったく把握していないのですが、怪我などによる主力選手の離脱によるものでしょうか。大学生プロとなった久岡はどんどんプレータイムを伸ばしていますね。

西宮ストークスはプレータイムの寡占具合が気になりますね。外国籍選手はもとより、谷と道原の負担が大きいようです。信州ブレイブウォリアーズと金沢武士団はかなりきれいな図になっていますので、こちらも全員バスケットと言って良さそうです。

西地区

f:id:rintaromasuda:20190130232036j:plain

バンビシャス奈良はハミルトンとパーマーの負担がかなりのようで、これだけ見ると3人目の外国籍選手がいないことが少し不安になります。契約解除となった広島のトンプソンは他の外国籍選手に比べるとそこまでプレータイムが長くなかったようですね。

熊本ヴォルターズもプレータイムが寡占傾向にあるようです。逆に愛媛オレンジバイキングスはプレータイムがシェアされていますが、例外的に笠原だけ非常にプレータイムが長いですね。興味深いです。

選手の起用状況をヒートマップで把握する

ざっと物事を把握するときには数字よりもビジュアルが便利な場合があります。今回は2018-19シーズンのここまで(31試合終了時点です)の選手の起用状況をヒートマップにして把握してみたいと思います。

y軸に各選手を並べ、x軸を左から1~31ゲーム目とし、それぞれの試合におけるその選手のプレータイムの長さを色の濃淡で表しています。プレータイムがなければ白であり、40分(もしくは延長でそれ以上)プレーした場合に向かって色がどんどん濃くなります。

東地区

f:id:rintaromasuda:20190130000939j:plain

ぱっと見で気になるのは渋谷のサクレとケリーのプレータイムがかなり嵩んでいることです。北海道のトラソリーニもミュレンズ加入まではかなり長い時間プレーをしてきたようです。秋田は中山もかなりプレーしていますね。あのプレースタイルでこのプレータイムはすごいです。

東京のビエリツァとウィリアムズが交互に起用されているのが分かりますね。斎藤が小島の、馬場が田中の欠場をそれぞれ埋め合わせている様子も分かります。千葉の小野の欠場から復帰したことや、比江島が栃木に加わったことによるプレータイムの変化も今後は注目です。

そう言えば北海道が内海新体制となったのは20ゲームからだと思いますが、そこから折茂さんがプレータイムを伸ばしているのもこれを見ると分かります。

中地区

f:id:rintaromasuda:20190130000951j:plain

新潟はガードナー、ハミルトン、五十嵐への負担の大きさがかなり目立ちます。同チームのベンチメンバーによる得点の割合が低いことは別の記事で書きましたが、ベテランが中心のメンバーという事もあり、後半戦の持久力への影響は気になるところです。

横浜は外国籍選手の入れ替えが序盤にかなりあったので、かなり多くの選手がこの図に顔を出す結果となっています。富山は3人目を獲得したようですが、これでスミスとライオンズの負担が多少は減ることが予想されます。

三遠はよい形でプレータイムがシェアされているように見えますね。三河は岡田の活躍が今後どうチームの起用に影響するかが見ものです。ここには含まれませんが、直近のゲームでは30分を超えるプレータイムを獲得していました。

西地区

f:id:rintaromasuda:20190130001003j:plain

まずは京都ですが、この31ゲーム目あたりでは実質7人ほどで回しているように見え、獲得した特別指定の選手や新たに獲得する選手などでロスターのバランスが取れてくるとよいです。

琉球は並里、橋本、岸本の3ガード体制がシーズン前に話題になっていましたが、その3人はこう見ると満遍なく起用され、石崎がそれをバックアップしているようです。アイラの欠場以降はスコットとエアーズの負担が増しています。

名古屋も日本人選手は満遍なく起用されているようです。横浜から移籍した満田がもう少しプレーしているイメージがありましたが、それでもきっちりとローテに組み込まれているようです。

サンプルコード

この記事の図を描いたときのコードがこちらにあります。

これまで3シーズンのすべてのゲームの観客動員数を見てみる

Bリーグ開幕からこれまで3シーズンのすべての観客動員数を見てみましょう。なお2018-19のデータは31試合終了時点までです。3シーズン合わせてなんとここまで2709試合。

レギュラーシーズンだけでもこのゲーム数です。日々これだけのゲームを回されている運営の方々には感謝の気持ちでいっぱいですね。ありがとうございます。

さて以下の図はそのすべてのゲームを時系列にプロットしたものです。B1とB2で色分けをしています。直線はいわゆる回帰直線で、要は直線でこれらの点を近似するとしたらどんな線になるのかを計算で求めたものです。

f:id:rintaromasuda:20190128231053j:plain

まず回帰直線ですが、嬉しいことにB1、B2ともの緩やかではありますが上昇傾向にありますね。Bリーグが目標にしている年平均成長率10%に届くかと言われれば届かないかもしれませんが、いずれにせよグッドニュースです。

また若干ではありますがB1とB2の差が詰まってきているようにも見えます。B1のトップチームはアリーナのサイズの問題で動員数をこれ以上増やすことが難しいチームも出ていますから、これは伸び代のあるB2が成長している証として素晴らしいのではないかと思います。

ちなみに上のデータは若干の季節変動があります。それを見るために同じデータを月ごとに分類してみましょう。こちらはシーズンで色分けを行っています。今回はこのブログではおなじみの箱ひげ図は使わず、ジッタープロットと呼ばれる図を使います。

f:id:rintaromasuda:20190128231109j:plain

季節変動ですが、開幕から年末年始に向けて徐々に動員数を減らし、そこからシーズン終盤の5月に向けてまた動員数が伸びていく様子がわかると思います。もちろんこんなこと図にしなくても分かりきっていることなのですが、こうして見てみると面白いものです。

今度は曜日ごとに分けてみましょう。今シーズンは平日開催を増やしており、特に地方都市での観客動員数への影響が心配されています。

f:id:rintaromasuda:20190128231125j:plain

今シーズンの水曜日はなかなか健闘しているのではないでしょうか?今シーズンの終盤に向けてどれだけの水曜日開催が残っているか知らないのですが、中盤時点でも前2シーズンにあまり見劣りしていませんから、終盤の水曜日開催ではさらに多い動員が期待できるのではと思います。

ちなみにそうやってシーズン間で値を比べたいのであれば、やはり箱ひげ図が便利ですね。ジッタープロットだとそれぞれのグループのデータ量のイメージが掴めるので、このように曜日ごとにデータ量が全然ちがうことを表現するのには都合が良いのですが。

サンプルコード

この記事にある図を描いたときのコードがこちらにあります。

ベンチメンバーはどれくらい得点を取っているのか?

各チームのベンチメンバーはどれくらい得点に貢献しているのでしょうか?先日シーホース三河のサザランドがいつもベンチスタートなことに気が付いてから気になっていました。

サザランドがいる三河の様に強力な帰化選手がいると外国籍選手をベンチスタートとすることもできます。結果としてベンチメンバーが多く得点に貢献する形になりそうです。

以下は各チームのベンチメンバーが総得点に占めた割合を箱ひげ図にしたものです。例えばあるチームが80点取ったとき、スタメンによる得点が50点であればこの値は30/80で37.5%となります。

f:id:rintaromasuda:20190118003746j:plain

アルバルク東京はベンチメンバーで40%くらいの得点を標準的に挙げていますね。そんなにアルバルク東京のゲームは追っていないですが、馬場もベンチスタートですし、竹内譲二がスタメンになると外国籍選手のひとりがベンチスタートになります。そういうことが影響しているのでしょう。

サザランドの三河は千葉ジェッツに次ぐ3番手ですが、この2チームは上述のように強力な帰化選手がいるパターンですね。大阪エヴェッサも同様でしょうか。川崎ブレイブサンダースはそこまでではないのは面白いです。

新潟と京都は極端にベンチメンバーによる得点の割合が低いですね。こちらはベンチメンバーというよりも、ガードナー、マブンガ、サイモンなど得点力のあるスタメン外国籍選手への得点力の依存の結果かもしれません。ちなみに新潟は今季既にベンチメンバーが0点というゲームがありました。

B2も見てみましょう。

f:id:rintaromasuda:20190118004617j:plain

B2では福島ファイアーボンズとバンビシャス奈良が抜け出しています。B1のトップのアルバルク東京よりは大分下がりますが、標準的に30%ほどはベンチメンバーによる得点のようです。

B2はB1ほど各チームに差がありませんが、島根スサノオマジックは中央値が15%にせまる勢いですし、全体的にB1よりも割合が低いですね。八王子ビートレインズの結果は、ご存知の通りそもそもベンチメンバーがあまりいないということによるものだと思われます。

最後にB1全体とB2全体を比べてみましょう。以下のようにB2の方がベンチメンバーによる得点の割合が低いことが分かります。

f:id:rintaromasuda:20190118005507j:plain

クォーターごとの得点、失点、得失点差を見てみる

今季から外国籍選手が常に2人コートに立てるようになり、ある意味では全部のクォーターが平等な扱いになりました。そこで各チームのクォーターごとの得点、失点、得失点差を見てみたいと思います。何か傾向があるでしょうか?

クォーターごとの得点

まずはクォーターごとの得点を見てみましょう。ちょっと図が込み入っておりますが、それぞれの箱ひげが今シーズンここまでの各クォーターの得点を表しています。

f:id:rintaromasuda:20190114220501j:plain

f:id:rintaromasuda:20190114220531j:plain

色々と気になる部分はありますが、千葉ジェッツ、サンロッカーズ渋谷、横浜ビー・コルセアーズ、滋賀レイクスターズなどが第2クォーターに得点を落としがちな部分がまず気になりました。

ひとつひとつ詳しく調べていけば理由は分かりそうですが、現時点の仮説はこれは選手のローテーションによるもので、チームとしては想定内だということです。得点力のある外国籍ビッグマンのプレータイムを第2クォーターに抑えがちなんじゃないかと予想します。

名古屋ダイヤモンドドルフィンズや大阪エヴェッサなど出だしがあまり芳しくないチームがいるのも面白いです。名古屋ダイヤモンドドルフィンズは今季は特にスリーポイント中心のチームですので、その辺りと何か相関がありそうです。

B2で圧倒的に目立つのが群馬クレインサンダーズの第3クォーターですね。これは一体どういう現象なのでしょうか。次に群馬のゲームを観ることがあれば第3クォーターに注目したいと思います。

クォーターごとの失点

続きましては失点です。同じ要領で見てみましょう。

f:id:rintaromasuda:20190114221603j:plain

f:id:rintaromasuda:20190114221618j:plain

千葉ジェッツは前半と後半でずいぶんと失点が違います。千葉ジェッツレベルのチームが後半に弱い、という結論には簡単にならないと思いますが、面白いポイントであることには間違いなさそうです。

新潟アルビレックスBBと富山グラウジーズの第3クォーターでの失点の増加具合は似ているような気がしますね。あと気になるのは川崎ブレイブサンダースの第4クォーターでしょうか。第4クォーターは他のクォーターと違ってガベージタイム等を含む場合がありますので単純に他のクォーターと比較できない面はありますが、気にはなりますね。

B2はバンビシャス奈良や福島ファイヤーボンズが千葉ジェッツと似たような傾向で後半に失点が多いです。信州ブレイブウォリアーズの第4クォーターも川崎ブレイブサンダースと似ていますが、今季すごく好調なチームだけにこちらはガベージタイムによるものかもしれません。

クォーターごとの得失点差

では最後に両方をがっちゃんこした得失点差を見てみましょう。

f:id:rintaromasuda:20190114223034j:plain

f:id:rintaromasuda:20190114223048j:plain

両方を合わせたものなので当たり前ですが、上述の傾向が重なったものになっております。全体的な傾向として感じるのが、やはりクォーターごと、特にハーフタイム前後ではゲームの雰囲気は変わるのかな、ということです。

バスケットボールは選手同士、選手とベンチのコミュニケーションが比較的に取りやすいスポーツで、細かな摺り合わせを連続していく必要のあるスポーツです。それを一番タイトに行えるのがやはりクォーター間だったりハーフタイムであったりするので、ヘッドコーチなりアシスタントコーチなりの実力が反映される部分かもしれません。

コード

この記事の図を描いたRのコードをこちらにアップロードしてあります。ご興味のある方はどうぞ。

B.LEAGUEデータ分析用Rパッケージ「bleaguer」を公開しました

※「Bリーガー」ではなく「Bリーグアール」と読みます

※この記事は随時更新される予定です

bleaguerって何?

bleaguerはプログラミング言語Rのパッケージ(拡張機能)です。このパッケージを使うと、B.LEAGUEのデータ分析をするのに便利なデータと機能が簡単にRで利用できます。

bleaguerは私が普段分析作業に使っているデータや関数などを便利にまとめたもので、ここ最近の分析作業はこのパッケージを自分で使いながら行っています。少なくても私の効率はこれで大分上がりました。

何ができるの?

  • 各種B.LEAGUEのデータをRに簡単にロードできます。現時点でサポートされているデータは以下の様なものです。
    • ゲームの日付
    • 開催アリーナ名称
    • 観客動員数
    • ゲームの種類(レギュラーシーズン、プレシーズン、ポストシーズン)
    • ホームチームとアウェイチーム
    • チームごとのスタッツ(基本的にはこのページに載っているスタッツです。)
  • 上記の生データを分析に適した形に結合した形で取得することもできます。

何ができないの?

  • プレイヤーの個人スタッツは、試合ごとトータルのみサポートしており、クォーターごとは現在サポートされていません。
  • このブログに出てくるような図を作る部分はこのパッケージでサポートしません。そこは利用側で行うという設計になっています(図を作る例はこちらの記事に掲載予定です。)

免責事項は?

  • B.LEAGUEさんの公式プロジェクトではありません。
  • データの中身の正誤は保証しません。ただし間違いをご指摘頂ければ直せます。
  • 最新の結果を即座に反映する予定はありません。
  • 後方互換性は死守しません(序盤は特に)
  • B.LEAGUEさんの意向等により、公開を中止する可能性があります。

Python使ってるんだけど?

残念ながらもこのパッケージは使えませんが、生データファイルへのアクセスは可能です。そちらを読み込みの上、ご自分でデータの結合、加工などして下されば似たようなことはできます。ファイルの場所は後述します。

Excel使ってるんだけど?

上述のように生データファイルへのアクセスは可能ですが、Excelだと読み込みに問題があるかもしれません。Excelで分析したい方がいましたら、効率的な方法を相談しましょう。

セットアップのやり方は?

※Dockerによる環境構築に対応しました。詳しくは下記リンク先の記事を参照してください。

まずは当然ですがRの実行環境を整えて頂く必要があります。RR Studioのインストールをお勧めします。方法の詳述はこの記事ではしません*1

Rのインストールが終わりましたら、devtoolsというパッケージをインストールしてください。こちらは普通に以下のコマンドをR Studioのコンソールに打つことでインストールできるはずです。

※どうやらdevtoolsに含まれるremotesというパッケージだけインストールするだけでも良さそうです(追記 2020.1.10)

install.packages("devtools")
# 上記でうまく行かない場合
install.packages("devtools", type = 'binary')

ここまで来るとbleaguerパッケージをインストールすることが可能です。以下のコマンドでインストール(私のgithubリポジトリよりダウンロードされます)、及びロードすることができます。

devtools::install_github("rintaromasuda/bleaguer")
library(bleaguer)

インストールは基本的には一度やればいいものです。ただし新しいバージョンがgithubにアップロードされた場合、それを適用するためには再度行う必要があります。新しいバージョンというのは、新しいデータが追加された場合も含みます。

インストール時に関連するいくつかのパッケージのインストールが求められますので行ってください。パッケージのアップデートについて訊かれる場合もあると思いますが、それは必須ではないはずです。お任せします。

どんな生データがロードされるの?

bleaguerをロードした瞬間に、以下のデータがR上にロードされるはずです。これらが生データとなります。

b.teams
b.events
b.games
b.games.summary
b.games.boxscore

b.teamsとb.eventsはいわゆるマスターデータです。Bリーグの各チーム(B1とB2のみ)の名称などのデータと、ゲームの名称や種類のデータが含まれています。

b.gamesはひとつのゲームにつきひとつのレコードができるデータで、そのゲームの種類、日付、観客動員数、対戦したチームのIDなどの情報が入っています。HomeTeamId/AwayTeamIdがb.teamsとTeamIdと、EventIdがb.eventsのEventIdとそれぞれ対応しています。

b.games.summaryはひとつのゲームにつきふたつのレコードができるデータで、そのゲームで対戦した両チームのチームスタッツが入っています。ScheduleKey、TeamIdでb.gamesと結合できるはずです。

b.games.boxscoreはゲームごとの個人スタッツが入っているデータです。こちらはScheduleKey、TeamIdに加えて選手ごとにPlayerIdが振られています。

詳述すると長くなってしまいますので、Rのstr()やsummary()やView()を使って中身を覗き見て頂くとわかり易いのではないかと思います。下記のようなコマンドの実行をすると中身が見られます。

View(b.teams)
str(b.events)
summary(b.games)
View(b.games.summary)
View(b.games.boxscore)

生データを使わないといけないの?

生データを結合するとなるとデータ間の関係などを理解する必要がある為、とっつきやすいように既に結合済みのデータを提供する関数も用意しました。

GetGameSummary()という関数を使うと、チームのスタッツを分析するのに丁度いいデータが取得できます。こちらもstrなどを用いて返り値を確認して頂ければと思いますが、このデータもひとつのゲームにつきふたつのレコードがあるものです。

チームAとチームBがそのゲームを戦ったとして、そのゲームの結果をチームAから見た場合と、チームBから見た場合のふたつが存在するイメージです。

サンプルコードは?

以下のサンプルコードですが、dplyrというパッケージを使うことを前提としております。これもinstall.packages(“dplyr”)でインストールができます。

# %>%などを使用するためにdplyrパッケージのインストールとロード
if (!require(dplyr)) {
install.packages("dplyr")
library(dplyr)
}
df <- GetGameSummary()
# 富山グラウジーズの2018-19レギュラーシーズンの全得点を取得
subset(df, TeamName == "富山" & Season == "2018-19" & Category == "Regular")$PTS
# 富山グラウジーズの2017-18ポストシーズンの全得点を取得
subset(df, TeamName == "富山" & Season == "2017-18" & Category == "Post")$PTS
# 2018-19レギュラーシーズンのB1各チームの平均点と平均失点を取得する
df %>%
filter(Season == "2018-19" & Category == "Regular" & League == "B1") %>%
group_by(TeamName) %>%
summarise(Points = mean(PTS),
OppPoints = mean(Opp.PTS)) %>%
as.data.frame()
# 栃木ブレックスのシーズンごと、アリーナごとの平均観客動員数と試合数を取得する
df %>%
filter(Category == "Regular" & TeamName == "栃木" & HomeAway == "Home") %>%
group_by(Season, Arena) %>%
summarize(MeanAttendance = mean(Attendance),
NumGames = n()) %>%
as.data.frame()
# 描画に使うggplot2パッケージのインストールとロード
if (!require(ggplot2)) {
install.packages("ggplot2")
library(ggplot2)
}
# 横浜ビー・コルセアーズの2018-19シーズンの得点をホーム、アウェイに分けて箱ひげ図にする
ggplot() +
geom_boxplot(data = subset(df, Category == "Regular" &
 Season == "2018-19" &
TeamName == "横浜"),
aes(x = HomeAway, y = PTS))
# 2018-19シーズンのB1各チームの失点を箱ひげ図にする
ggplot() +
geom_boxplot(data = subset(df, Category == "Regular" &
Season == "2018-19" &
League == "B1"),
aes(x = TeamName, y = Opp.PTS))

サンプルコードは必要に応じて随時追加する予定です。上記と同様のものですが、こちらにアップロードもしてあります。また今後ブログ記事の作成にbleaguerを使用した場合、そのコードもこちらのカテゴリにて随時シェアする予定です。

生データのファイルはどこに?

同じgithubリポジトリのここにCSV形式でアップロードされています。

質問がある場合は?

もし利用したいという方がいらして、利用方法で何かしら質問がありましたら私のTwitterまでお問合せ下さい。その用途にSlackグループを作成しましたので、そちらにてお話させて頂ければと思っております。

参照

追記(2020.1.19)

*1:Rのバージョンですが、3.5以降だとbleaguerのインストールに問題がある場合があるようです(Windowsで問題を確認。)現在3.4.xを推奨です。