CドライブのSSDの換装を行った

以前からCドライブの容量が足りなくて困っていたので、今回思い切って120GB SSDから500GB SSDに換装した。 参考にしたページ。

www.iyamaittane.com

購入した商品はこのページの物にした。1TBのSSDも考えたが1万円を超えるのでパス。購入したSSDを初期化するのは一瞬で終わった。続いてCドライブのクローンはシステムクローンにするかクローンにするかわからなかったので取りあえずクローンにした。25分で終わった。
 あとは物理的に交換して電源を入れたら無事起動した。BIOSで起動順番の変更もなかった。ちゃんとCドライブに容量が増えていたが一度再起動を求められた。これから容量不足のためインストールできなかったソフトを入れていこう。

kaggleで上位に入るための探索的データ解析入門

1章 探索的データ解析の概要

 省略

2章 データの意味と種類を知れば道が決まる

 省略

3章 クリーニングでゴミを取り除け

欠損値を削除

f:id:bitop:20200425101524p:plain
f:id:bitop:20200425101834p:plain

年収データに外れ値がある

f:id:bitop:20200425102032p:plain
外れ値を除去するとき本ではdf = df[df['salary']>800]となっていたが
df = df[df['salary']<800]だと思われる。
f:id:bitop:20200425102238p:plain
f:id:bitop:20200425102259p:plain
箱ヒゲ図
f:id:bitop:20200425102351p:plain
乗船料金にも外れ値があるようでこれも除去
f:id:bitop:20200425102511p:plain
除去後
f:id:bitop:20200425102614p:plain
表記ゆれ
f:id:bitop:20200425102719p:plain
違うデータとして認識される
f:id:bitop:20200425102807p:plain
小文字に統一する
f:id:bitop:20200425102840p:plain
重複除去
f:id:bitop:20200425103123p:plain
f:id:bitop:20200425103147p:plain
ヒートマップを使って重複データを見つける
f:id:bitop:20200425103313p:plain
除去後
f:id:bitop:20200425103344p:plain

4章 データ分析は切り口が全て

f:id:bitop:20200425103420p:plain
統計値
f:id:bitop:20200425103527p:plain
カテゴリデータの統計値
f:id:bitop:20200425103538p:plain
時系列データの統計値
f:id:bitop:20200425103638p:plain
データセットをtipsに変更
f:id:bitop:20200425103715p:plain
ヒストグラム表示
f:id:bitop:20200425103811p:plain
チップ額でレベル分け
f:id:bitop:20200425103918p:plain

5章 データ分析手法 基本の6パターン

データセットはtitanic、ヒストグラム
f:id:bitop:20200425104033p:plain
ビン幅を変えると印象が微妙に変化
f:id:bitop:20200425104203p:plain
性別で重ね合わせる
f:id:bitop:20200425104247p:plain
客室クラスごとの年齢を比較
f:id:bitop:20200425104334p:plain
客室ごとの年齢の箱ヒゲ図
f:id:bitop:20200425104443p:plain
客室ごとの年齢のバイオリン図
f:id:bitop:20200425104526p:plain
ここからデータセットはflights(飛行機の旅客数)
f:id:bitop:20200425104651p:plain
1949年の月ごと
f:id:bitop:20200425104734p:plain
他の年の月ごと
f:id:bitop:20200425104815p:plain
ここからtipsのデータセット
支払い総額とチップの相関関係
f:id:bitop:20200425104944p:plain
喫煙者と非喫煙者で絞り込む
f:id:bitop:20200425105014p:plain
分離して表示
f:id:bitop:20200425105515p:plain
食事の時間帯を絞る
f:id:bitop:20200425105603p:plain
ヒートマップ
f:id:bitop:20200425105631p:plain

学生が学ぶMathematica入門を読む

mathematicaの数式処理エンジンが無料で入手できたので「学生が学ぶMathematica入門」で練習した。

qiita.com

f:id:bitop:20200412113804p:plain

f:id:bitop:20200412114101p:plain

f:id:bitop:20200412113931p:plain

f:id:bitop:20200412114201p:plain

f:id:bitop:20200412114245p:plain

f:id:bitop:20200412114350p:plain

かなり簡単にできる。本家には敵わないところもある。アニメーションや作画したグラフを操作するといったことは制限がある。

Get-Started-with-Your-Questions-EDA+Model-NN

import scipy
print(scipy.__version__)

f:id:bitop:20200103092930p:plain

リンク先

www.kaggle.com

# This Python 3 environment comes with many helpful analytics libraries installed
# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python
# For example, here's several helpful packages to load in 

#import required packages
#basics
import pandas as pd 
import numpy as np

#misc
import gc
import time
import warnings

#stats
import scipy as sp
"""
from scipy.misc import imreadでインポートするとエラーがでる
cannot import name 'imread' from 'scipy.misc'
対処法
https://qiita.com/enoughspacefor/items/c490ec7195cf66fa286f
深層学習とかでのPythonエラー「ImportError: cannot import name 'imread' from 'scipy.misc' 」への対処

scipyのバージョンが1.3にあがったのでエラーがでる

"""
from imageio import imread

from scipy import sparse
import scipy.stats as ss

#viz
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec  #https://qiita.com/simonritchie/items/da54ff0879ad8155f441 [matplotlib]プロットの複雑なレイアウトはGridSpecが便利かも、という話
import seaborn as sns
"""
ワード‐クラウド(word cloud)
文章中で出現頻度が高い単語を複数選び出し、その頻度に応じた大きさで図示する手法。 ウェブページやブログなどに
頻出する単語を自動的に並べることなどを指す。 文字の大きさだけでなく、色、字体、向きに変化をつけることで、
文章の内容をひと目で印象づけることができる。
"""
# pip install wordcloud要
from wordcloud import WordCloud ,STOPWORDS
from PIL import Image
import matplotlib_venn as venn

#nlp
import string
import re    #for regex
import nltk
from nltk.corpus import stopwords
"""
https://www.ogis-ri.co.jp/otc/hiroba/technical/similar-document-search/part4.html
はじめての自然言語処理
第1回 類似文書検索の手法と精度比較
第2回 Rasa NLU を用いた文書分類と固有表現抽出
第3回 BERT を用いた自然言語処理における転移学習
第4回 spaCy/GiNZA を用いた自然言語処理 *こんかいコレ
第5回 pke によるキーフレーズ抽出
第6回 OSS によるテキストマイニング
"""
import spacy
from nltk import pos_tag
from nltk.stem.wordnet import WordNetLemmatizer 
from nltk.tokenize import word_tokenize
# Tweet tokenizer does not split at apostophes which is what we want
from nltk.tokenize import TweetTokenizer   


#FeatureEngineering
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer, HashingVectorizer
from sklearn.decomposition import TruncatedSVD
from sklearn.base import BaseEstimator, ClassifierMixin
from sklearn.utils.validation import check_X_y, check_is_fitted
from sklearn.linear_model import LogisticRegression
from sklearn import metrics
from sklearn.metrics import log_loss
from sklearn.model_selection import StratifiedKFold,KFold
from sklearn.model_selection import train_test_split
import tensorflow as tf 


#settings
start_time=time.time()
color = sns.color_palette()
sns.set_style("dark")
eng_stopwords = set(stopwords.words("english"))
warnings.filterwarnings("ignore")

lem = WordNetLemmatizer()
tokenizer=TweetTokenizer()


from wordcloud import WordCloud, STOPWORDS, ImageColorGenerator

%matplotlib inline

# Input data files are available in the "../input/" directory.
# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory

import os
for dirname, _, filenames in os.walk('/kaggle/input'):
    for filename in filenames:
        print(os.path.join(dirname, filename))

# Any results you write to the current directory are saved as output.
# pip install keras要
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.layers import Dense, Input, LSTM, Embedding, Dropout, Activation, Conv1D, GRU, BatchNormalization
from keras.layers import Bidirectional, GlobalMaxPool1D, MaxPooling1D, Add, Flatten, Masking
from keras.layers import GlobalAveragePooling1D, GlobalMaxPooling1D, concatenate, SpatialDropout1D
from keras.models import Model, load_model
from keras import initializers, regularizers, constraints, optimizers, layers, callbacks
from keras import backend as K
from keras.engine import InputSpec, Layer
from keras.optimizers import Adam
from keras.callbacks import ModelCheckpoint, TensorBoard, Callback, EarlyStopping, ReduceLROnPlateau
from sklearn.preprocessing import OneHotEncoder

f:id:bitop:20200103093200p:plain

Data Understanding

## load the data 
ROOT = "input/"
train = pd.read_csv(ROOT+'train.csv')
test = pd.read_csv(ROOT+'test.csv')
sub = pd.read_csv(ROOT+'sample_submission.csv')

Quick look at the train

train.head()

f:id:bitop:20200103093312p:plain

# 41 columns
print(train.columns)

f:id:bitop:20200103093355p:plain

train.shape

f:id:bitop:20200103093428p:plain

# question_title 質問のタイトル
print(train['question_title'][0])
# 訳 マクロレンズの代わりに延長チューブを使用すると、何が失われますか?
print(train['question_title'][1])
# 都市とスプロール/メトロプレックスの違いは何ですか...ダウンタウンと商業地区の違い

f:id:bitop:20200103093553p:plain

# question_user_name 質問した人の名前?
print(train['question_user_name'].unique())
print(len(train['question_user_name'].unique()))

f:id:bitop:20200103093636p:plain

#question_body 質問の中身?
print(train['question_body'][0])
"""
安価なマクロ写真で遊んだ後(読み方:レンズを逆にした、回転レンズをまっすぐなレンズに取り付けた、受動的な延長管)、私はこれをさらに進めたいと思います。 私が使用した技術の問題は、焦点が手動であり、開口制御がせいぜい問題であるということです。 これにより、私の被写体は静止した被写体に限定されました(読む:死んだ昆虫)今、春が近づいているので、生きている昆虫を撃ちたいと思います。 このためには、オートフォーカスと設定可能な絞りが大きな助けになると思います。
したがって、1つの明らかだが高価なオプションはマクロレンズ(たとえばEF 100mmマクロ)です。しかし、私はまだ別のプライムレンズにはあまり興味がありません。 代替手段は、電気延長チューブです。
最大焦点距離を除き、マクロレンズの代わりにチューブ(EF70-200 / 2.8などのファインレンズと結合)を使用すると何が失われますか?
"""
print(train['question_body'][1])
"""
Shadowrunの第5版メインブックで、p 231のスパム値がどのような場所を指しているのかを理解しようとしています。
p 15で、スプロールはプレックスであり、プレックスは「メトロポリタンの略でメトロポリタンコンプレックス」です。 Googleによると、メトロプレックスは「非常に大きな大都市圏、特に2つ以上の都市の集合体」です。 ダウンタウンの都市とスプロールダウンタウンの密度は似ている傾向がありますが、何らかの理由でスプロール(郊外を含む?)のスパムゾーンノイズ評価が高くなっています(p 231)。 同様に、繁華街は商業地区よりも密集していて騒がしい(オフィスビルや露店など)と考えています。 屋外モール。 ノイズ評価により、私はこれについて間違って考えていると思います。 それらのより良い考え方は何ですか?
"""

f:id:bitop:20200103093727p:plain

#question_user_page Stack Exchange Networkというサイトから引用されている
for i in range(10):
    print(train['question_user_page'][i])

f:id:bitop:20200103093814p:plain

# answer 答え
print(train['answer'][0])
"""
私は延長チューブを手に入れたばかりなので、ここがスキニーです。

   ...チューブを使用すると何が失われますか?

非常にかなりの量の光! レンズの端からセンサーまでの距離を長くすると、光が数回停止する場合があります。 通常は撮影を停止するという事実と組み合わせて、ISOを大幅に上げる必要があることを期待してください。
通常、マクロは非常にシャープであると考えられていますが、70-200mm 2.8は非常にシャープであると思われます。
多くのマクロに典型的な超低歪み。
自由度はまだかなり制限されるため、ボケについてはあまり心配しません。
私の50mmに加えて、完全な60mmの延長チューブは、レンズの前で数インチのDOFをもたらします。 私の70-300では、おそらくレンズの前の約2〜3フィートからレンズの前の約1フィートまでです。"""

f:id:bitop:20200103093908p:plain

# answer_user_name 質問に答えてくれた人の名前

print(train['answer_user_name'].unique())
print(len(train['answer_user_name'].unique()))

f:id:bitop:20200103093950p:plain

# answer_user_page 質問に答えてくれた人のProfileページ
for i in range(10):
    print(train['answer_user_page'][i])

f:id:bitop:20200103094050p:plain

  # url 質問と答えのページ Yahoo知恵袋のようなサイト
for i in range(10):
    print(train['url'][i])

f:id:bitop:20200103094132p:plain

print(train['category'].unique())
print(len(train['category'].unique()))
# LIFE_ARTS ?
# CULTURE 文化
# SCIENCE 科学
# STACKOVERFLOW スタックオーバーフロー
# TECHNOLOGY テクノロジ

f:id:bitop:20200103094252p:plain

print(train['host'].unique())
print(len(train['host'].unique()))

f:id:bitop:20200103094333p:plain

test.head()

f:id:bitop:20200103094421p:plain

#trainよりかなり減っている 11
test.columns

f:id:bitop:20200103094503p:plain

all_train_columns = list(train.columns)
question_answer_cols = all_train_columns[:11]
question_target_cols = all_train_columns[11:32]
answer_target_cols  = all_train_columns[32:41]

question_answer_cols

f:id:bitop:20200103094635p:plain

question_target_cols

f:id:bitop:20200103094704p:plain

answer_target_cols  

f:id:bitop:20200103094737p:plain

## Check one question and answer  
questiont = train["question_title"][0]
questionb = train["question_body"][0]
answer1 = train["answer"][0]

print(f"The First Question Topic  is : {questiont}\n\n ")
print(f"The First Question Details are :  \n\n {questionb}\n\n ")
print(f"The First answer is :\n\n {answer1}\n\n ")

f:id:bitop:20200103094845p:plain

## lets see some distributions of questions targets

# question_asker_intent_understanding
# question_body_critical
# question_conversational
# question_expect_short_answer
# question_fact_seeking
# について分布グラフを描画している

# hist=Falseはヒストグラムではなくkde=Trueガウス密度推定値を描画することを指示している
plt.figure(figsize=(20, 5))

sns.distplot(train[question_target_cols[0]], hist= False , rug= False ,kde=True, label =question_target_cols[0],axlabel =False )
sns.distplot(train[question_target_cols[1]], hist= False , rug= False,label =question_target_cols[1],axlabel =False)
sns.distplot(train[question_target_cols[2]], hist= False , rug= False,label =question_target_cols[2],axlabel =False)
sns.distplot(train[question_target_cols[3]], hist= False , rug= False,label =question_target_cols[3],axlabel =False)
sns.distplot(train[question_target_cols[4]], hist= False , rug= False,label =question_target_cols[4],axlabel =False)
plt.show()

f:id:bitop:20200103095004p:plain

## lets see some distributions of answer targets
plt.figure(figsize=(20, 5))

sns.distplot(train[answer_target_cols[0]], hist= False , rug= False ,kde=True, label =answer_target_cols[0],axlabel =False )
sns.distplot(train[answer_target_cols[1]], hist= False , rug= False,label =answer_target_cols[1],axlabel =False)
#sns.distplot(train[answer_target_cols[2]], hist= False , rug= False,label =answer_target_cols[2],axlabel =False)
#sns.distplot(train[answer_target_cols[3]], hist= False , rug= False,label =answer_target_cols[3],axlabel =False)
sns.distplot(train[answer_target_cols[4]], hist= False , rug= False,label =answer_target_cols[4],axlabel =False)
plt.show()
## Removed two columns as value was quite high and other graphs were not visible .

## Lets see the words of first question

plt.figure(figsize=(20, 5))

text = train.question_body[0]

# Create and generate a word cloud image:
wordcloud = WordCloud().generate(text)

# Display the generated image:
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
plt.show()

f:id:bitop:20200103095125p:plain

#アンサーの文書
### Lets see the words of first answer
plt.figure(figsize=(20, 5))

text = train.answer[0]

# Create and generate a word cloud image:
wordcloud = WordCloud().generate(text)

# Display the generated image:
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
plt.show()

f:id:bitop:20200103095234p:plain

##How many words are there in all questions ? 
# 全ての質問の単語の数は
text = " ".join(question_body for question_body in train.question_body)
print(type(text))
print(test[0:10])
print ("There are {} words in the combination of all questions.".format(len(text)))

f:id:bitop:20200103095338p:plain

NFL-1st-and-Future-2019をやってみる

インポート

import numpy as np
import pandas as pd
import matplotlib.pylab as plt
import seaborn as sns
# matplotlib.patchesは円や長方形などの図形を描く。
import matplotlib.patches as patches
sns.set_style("whitegrid")

!dir input

f:id:bitop:20200101130730p:plain

f:id:bitop:20200101130801p:plain

playlist = pd.read_csv('input/PlayList.csv')
inj = pd.read_csv('input/InjuryRecord.csv')
trk = pd.read_csv('input/PlayerTrackData.csv')

inj.head()

f:id:bitop:20200101131027p:plain

print(inj.shape)

print('-'*50,'PlayerKey','-'*50)
print(inj['PlayerKey'].unique()); print(len(inj['PlayerKey'].unique()))

print('-'*50,'GameID','-'*50)
print(inj['GameID'].unique()); print(len(inj['GameID'].unique()))

print('-'*50,'PlayKey','-'*50)
print(inj['PlayKey'].unique()); print(len(inj['PlayKey'].unique()))

print('-'*50,'BodyPart','-'*50)
print(inj['BodyPart'].unique()); print(len(inj['BodyPart'].unique()))

print('-'*50,'Surface','-'*50)
print(inj['Surface'].unique()); print(len(inj['Surface'].unique()))

print('-'*50,'DM_M1','-'*50)
print(inj['DM_M1'].unique()); print(len(inj['DM_M1'].unique()))

print('-'*50,'DM_M7','-'*50)
print(inj['DM_M7'].unique()); print(len(inj['DM_M7'].unique()))

print('-'*50,'DM_M28','-'*50)
print(inj['DM_M28'].unique()); print(len(inj['DM_M28'].unique()))

print('-'*50,'DM_M42','-'*50)
print(inj['DM_M42'].unique()); print(len(inj['DM_M42'].unique()))

f:id:bitop:20200101132434p:plain  

# 28 Injurties without PlayKey
# playKeyに28の欠損値がある
inj['PlayKey'].isna().sum() 

# BodyPartは5パートある(足首とか)
# そのパートごとにPlayerが何人いるか数えて棒グラフにする。膝が一番多い、次が足首
inj.groupby('BodyPart').count()['PlayerKey'] \
    .sort_values() \
    .plot(kind='bar', figsize=(15, 5), title='Count of injuries by Body Part')
plt.show()

f:id:bitop:20200101132600p:plain

# SurfaceはSynthetic,Natural
# チエーンがつながっているのでよくわからないので、分解して表示させた。
inj.groupby(['BodyPart','Surface']).count()

f:id:bitop:20200101132707p:plain

inj.groupby(['BodyPart','Surface']) \
    .count() \
    .unstack('BodyPart')['PlayerKey']

f:id:bitop:20200101133048p:plain

inj.groupby(['BodyPart','Surface']) \
    .count() \
    .unstack('BodyPart')['PlayerKey'] \
    .T.sort_values('Natural').T

f:id:bitop:20200101133133p:plain

inj.groupby(['BodyPart','Surface']) \
    .count() \
    .unstack('BodyPart')['PlayerKey'] \
    .T.sort_values('Natural').T \
    .sort_values('Ankle') 

f:id:bitop:20200101133207p:plain

# Surfaceの意味がわからないのでいまひとつデータの解釈ができない
inj.groupby(['BodyPart','Surface']) \
    .count() \
    .unstack('BodyPart')['PlayerKey'] \
    .T.sort_values('Natural').T \
    .sort_values('Ankle') \
    .plot(kind='bar', figsize=(15, 5), title='Injury Body Part by Turf Type')
plt.show()

f:id:bitop:20200101133257p:plain

Playlist Data

playlist.head()  

f:id:bitop:20200101133346p:plain

# Quarterback : クオータバック
# Wide Receiver : ワイド・レシーバー
# Linebacker : ラインバッカー
# Running Back : ランニングバック
# Defensive Lineman : ラインマン 
# Tight End : タイトエンド
# Safety : セイフティ
# Cornerback : コーナーバック
# Offensive Lineman : オフェンシブライン

print(playlist['RosterPosition'].unique())

f:id:bitop:20200101133433p:plain

print(playlist['PlayerDay'].unique())

f:id:bitop:20200101133551p:plain

# スタジアムタイプ
print(playlist['StadiumType'].unique())

f:id:bitop:20200101133632p:plain

# フィールドが天然芝か合成芝かな
print(playlist['FieldType'].unique())

f:id:bitop:20200101133705p:plain

# 天気
# Clear and warm : Clear and warm
# Mostly Cloudy : だいたい曇など
print(playlist['Weather'].unique())

f:id:bitop:20200101133746p:plain

# そのときのPlay Type
print(playlist['PlayType'].unique())

f:id:bitop:20200101133825p:plain

# RosterPositionとよく似ている、欠損値らしきものも
print(playlist['Position'].unique())

f:id:bitop:20200101133916p:plain

# PositionともRosterPositionとよく似ている
print(playlist['PositionGroup'].unique())

f:id:bitop:20200101133956p:plain

# Number of unique plays in the playlist dataset
playlist['PlayKey'].nunique()

playlist[['PlayKey','PlayType']].drop_duplicates() \
    .groupby('PlayType').count()['PlayKey'] \
    .sort_values() \
    .plot(kind='barh',
         figsize=(15, 6),
          color='black',
         title='Number of plays provided by type')
plt.show()

f:id:bitop:20200101134103p:plain

Match Player info with injury data(プレーヤー情報と傷害データを一致させる)

# PlayerKeyとPlaykeyとGameIDが一致する。全部で20のカラムとなる
inj_detailed = inj.merge(playlist)

# 怪我をするPlayerはLinebacker Wide Receiverが多い
inj_detailed.groupby('RosterPosition').count()['PlayerKey'] \
    .sort_values() \
    .plot(figsize=(15, 5), kind='barh', title='Injured Players by Position')
plt.show()

f:id:bitop:20200101134223p:plain

# 怪我をするPlayTypeはPass Rushが多い
inj_detailed.groupby('PlayType').count()['PlayerKey'] \
    .sort_values() \
    .plot(figsize=(15, 5), kind='barh', title='Injured Players by PlayType', color='green')
plt.show()

f:id:bitop:20200101134309p:plain

Distribution of Injury Types(傷害タイプの分布)

# ポジションごとの怪我の部位の率
inj_detailed.groupby(['RosterPosition','BodyPart']) \
    .count() \
    .unstack('BodyPart')['PlayerKey'] \
    .T.apply(lambda x: x / x.sum()) \
    .sort_values('BodyPart').T.sort_values('Ankle', ascending=False) \
    .plot(kind='barh',
          figsize=(15, 5),
          title='Injury Body Part by Player Position',
          stacked=True)
plt.show()

f:id:bitop:20200101134412p:plain

# PlayTypeごとの怪我の部位率
# 特徴的な分布がみられる
inj_detailed.groupby(['PlayType','BodyPart']) \
    .count() \
    .unstack('BodyPart')['PlayerKey'] \
    .T.apply(lambda x: x / x.sum()) \
    .sort_values('BodyPart').T.sort_values('Ankle', ascending=False) \
    .plot(kind='barh',
          figsize=(15, 5),
          title='Injury Body Part by Play Type',
          stacked=True)
plt.show()

f:id:bitop:20200101134500p:plain

# ポジションごとのフィールドの種類の分布
inj_detailed.groupby(['RosterPosition','Surface']) \
    .count() \
    .unstack('Surface')['PlayerKey'] \
    .T.apply(lambda x: x / x.sum()) \
    .sort_values('Surface').T.sort_values('Natural', ascending=False) \
    .plot(kind='barh',
          figsize=(15, 5),
          title='Injury Body Part by Turf Type',
          stacked=True)
plt.show()

f:id:bitop:20200101134549p:plain

Plotting Plays

# 
def create_football_field(linenumbers=True,
                          endzones=True,
                          highlight_line=False,
                          highlight_line_number=50,
                          highlighted_name='Line of Scrimmage',
                          fifty_is_los=False,
                          figsize=(12, 6.33)):
    """
    Function that plots the football field for viewing plays.
    Allows for showing or hiding endzones.
    """
    rect = patches.Rectangle((0, 0), 120, 53.3, linewidth=0.1,
                             edgecolor='r', facecolor='darkgreen', zorder=0)

    fig, ax = plt.subplots(1, figsize=figsize)
    ax.add_patch(rect)

    plt.plot([10, 10, 10, 20, 20, 30, 30, 40, 40, 50, 50, 60, 60, 70, 70, 80,
              80, 90, 90, 100, 100, 110, 110, 120, 0, 0, 120, 120],
             [0, 0, 53.3, 53.3, 0, 0, 53.3, 53.3, 0, 0, 53.3, 53.3, 0, 0, 53.3,
              53.3, 0, 0, 53.3, 53.3, 0, 0, 53.3, 53.3, 53.3, 0, 0, 53.3],
             color='white')
    if fifty_is_los:
        plt.plot([60, 60], [0, 53.3], color='gold')
        plt.text(62, 50, '<- Player Yardline at Snap', color='gold')
    # Endzones
    if endzones:
        ez1 = patches.Rectangle((0, 0), 10, 53.3,
                                linewidth=0.1,
                                edgecolor='r',
                                facecolor='blue',
                                alpha=0.2,
                                zorder=0)
        ez2 = patches.Rectangle((110, 0), 120, 53.3,
                                linewidth=0.1,
                                edgecolor='r',
                                facecolor='blue',
                                alpha=0.2,
                                zorder=0)
        ax.add_patch(ez1)
        ax.add_patch(ez2)
    plt.xlim(0, 120)
    plt.ylim(-5, 58.3)
    plt.axis('off')
    if linenumbers:
        for x in range(20, 110, 10):
            numb = x
            if x > 50:
                numb = 120 - x
            plt.text(x, 5, str(numb - 10),
                     horizontalalignment='center',
                     fontsize=20,  # fontname='Arial',
                     color='white')
            plt.text(x - 0.95, 53.3 - 5, str(numb - 10),
                     horizontalalignment='center',
                     fontsize=20,  # fontname='Arial',
                     color='white', rotation=180)
    if endzones:
        hash_range = range(11, 110)
    else:
        hash_range = range(1, 120)

    for x in hash_range:
        ax.plot([x, x], [0.4, 0.7], color='white')
        ax.plot([x, x], [53.0, 52.5], color='white')
        ax.plot([x, x], [22.91, 23.57], color='white')
        ax.plot([x, x], [29.73, 30.39], color='white')

    if highlight_line:
        hl = highlight_line_number + 10
        plt.plot([hl, hl], [0, 53.3], color='yellow')
        plt.text(hl + 2, 50, '<- {}'.format(highlighted_name),
                 color='yellow')
    return fig, ax

Plot path of injured player

# trkは1秒に10回のplayerの位置情報
trk.head()

f:id:bitop:20200101134743p:plain

trk.tail()

f:id:bitop:20200101134812p:plain

trk.shape

f:id:bitop:20200101134845p:plain

fig, ax = create_football_field()

f:id:bitop:20200101134920p:plain

# player idを取り出しその位置情報(xとy)で散布図で描画させている
# query()メソッドの条件文字列の中で変数を使用するには変数名の前に@をつける。 https://note.nkmk.me/python-pandas-query/
example_play_id = inj['PlayKey'].values[0]
print(example_play_id)
fig, ax = create_football_field()
trk.query('PlayKey == @example_play_id').plot(kind='scatter', x='x', y='y', ax=ax, color='orange')
plt.show()

f:id:bitop:20200101135015p:plain

Plotting every route of injured players

# Loop through all 99 inj plays
inj_play_list = inj['PlayKey'].tolist()
fig, ax = create_football_field()
for playkey, inj_play in trk.query('PlayKey in @inj_play_list').groupby('PlayKey'):
    inj_play.plot(kind='scatter', x='x', y='y', ax=ax, color='orange', alpha=0.2)
plt.show()

f:id:bitop:20200101135115p:plain

Plotting routes of some non-injured players(負傷していないプレイヤーのルートをプロットする)

import random
playids = trk['PlayKey'].unique() #.sample(100)
non_inj_play = [x for x in playids if x not in inj_play_list]
sample_non_inj_plays = random.sample(non_inj_play, 100)

fig, ax = create_football_field()
for playkey, inj_play in trk.query('PlayKey in @sample_non_inj_plays').groupby('PlayKey'):
    inj_play.plot(kind='scatter', x='x', y='y', ax=ax, color='red', alpha=0.2)
plt.show()

f:id:bitop:20200101135221p:plain

Distribution of tracking info for players with injuries(負傷したプレーヤーの追跡情報の配布)

print(trk['s'].max())
print(trk['s'].min())

f:id:bitop:20200101135315p:plain

# playerのスピードを負傷者と非負傷者とで分布の違いを比較
fig, axes = plt.subplots(1, 2)

trk.query('PlayKey in @inj_play_list')['s'].plot(kind='hist',
                                                 title='Distribution of player Speed injured',
                                                 figsize=(15, 5), bins=30, ax=axes[0],ylim=[0,10000])
trk.query('PlayKey not in @inj_play_list')['s'].sample(10000).plot(kind='hist',
                                                 title='Distribution of player Speed not injured',
                                                 figsize=(15, 5), bins=30, ax=axes[1], color='orange',ylim=[0,10000])
plt.show()

f:id:bitop:20200101135403p:plain

fig, axes = plt.subplots(1, 2)

trk.query('PlayKey in @inj_play_list')['o'].plot(kind='hist',
                                                 title='Distribution of player Orientation injured',
                                                 figsize=(15, 5), bins=30, ax=axes[0],ylim=[0,1600])
trk.query('PlayKey not in @inj_play_list')['o'].sample(10000).plot(kind='hist',
                                                 title='Distribution of player Orientation not injured',
                                                 figsize=(15, 5), bins=30, ax=axes[1], color='orange',ylim=[0,1600])
plt.show()

f:id:bitop:20200101135446p:plain

Differences in x, y could be attributed to the player positions which are more likely to have injury

(負傷の可能性が高いプレーヤーの位置に起因する可能性があります。)

# x座標で怪我の分布、広く分布しておりこれっと行った特徴なし
fig, axes = plt.subplots(1, 2)

trk.query('PlayKey in @inj_play_list')['x'].plot(kind='hist',
                                                 title='Distribution of player X injured',
                                                 figsize=(15, 5), bins=30, ax=axes[0],ylim=[0,2000])
trk.query('PlayKey not in @inj_play_list')['x'].sample(10000).plot(kind='hist',
                                                 title='Distribution of player X not injured',
                                                 figsize=(15, 5), bins=30, ax=axes[1], color='orange',ylim=[0,2000])
plt.show()

f:id:bitop:20200101135544p:plain

# 縦軸方向では中央で怪我が発生しやすいとわかりやすい特徴がでた
fig, axes = plt.subplots(1, 2)

trk.query('PlayKey in @inj_play_list')['y'].plot(kind='hist',
                                                 title='Distribution of player Y injured',
                                                 figsize=(15, 5), bins=30, ax=axes[0])
trk.query('PlayKey not in @inj_play_list')['y'].sample(10000).plot(kind='hist',
                                                 title='Distribution of player Y not injured',
                                                 figsize=(15, 5), bins=30, ax=axes[1], color='orange')
plt.show()

f:id:bitop:20200101135631p:plain

Compass plots of direction/velocity(方向/速度のコンパスプロット)

def compass(angles, radii, arrowprops=None, ax=None):
    """
    * Modified for NFL data plotting
    Compass draws a graph that displays the vectors with
    components `u` and `v` as arrows from the origin.

    Examples
    --------
    >>> import numpy as np
    >>> u = [+0, +0.5, -0.50, -0.90]
    >>> v = [+1, +0.5, -0.45, +0.85]
    >>> compass(u, v)
    """

    #angles, radii = cart2pol(u, v)
    if ax is None:
        fig, ax = plt.subplots(subplot_kw=dict(polar=True))

    kw = dict(arrowstyle="->", color='k')
    if arrowprops:
        kw.update(arrowprops)
    [ax.annotate("", xy=(angle, radius), xytext=(0, 0),
                 arrowprops=kw) for
     angle, radius in zip(angles, radii)]

    ax.set_ylim(0, np.max(radii))

    return ax

def plot_play_compass(playkey, **kwargs):
    d = trk.loc[trk['PlayKey'] == playkey].copy()
    d['dir_theta'] = d['dir'] * np.pi / 180
    # Calculate velocity in meters per second
    d['dis_meters'] = d['dis'] / 1.0936  # Add distance in meters
    # Speed
    d['dis_meters'] / 0.01
    d['v_mps'] = d['dis_meters'] / 0.1

    ax = compass(d['dir_theta'], d['v_mps'],
                  arrowprops={'alpha': 0.3},
                **kwargs)
    return ax

fig, axes = plt.subplots(2, 3,  subplot_kw=dict(polar=True), figsize=(15, 10))
axes = np.array(axes)
axes = axes.reshape(-1)

i = 0
for p in inj_detailed['PlayKey'].values[:6]:
    plot_play_compass(p, ax=axes[i])
    axes[i].set_title(f'PlayKey: {p}')
    i += 1
plt.show()

f:id:bitop:20200101135754p:plain

Player Position vs Compass Plot(プレイヤーの位置とコンパスのプロット)

# Play Details
example_play_id = inj['PlayKey'].values[6]
inj_detailed.query('PlayKey == @example_play_id')

f:id:bitop:20200101135845p:plain

fig, ax = create_football_field(ax)
ax.set_title(f'PlayKey: {example_play_id}')
trk.query('PlayKey == @example_play_id').plot(kind='scatter', x='x', y='y', ax=ax, color='orange')
plt.show()

ax = plot_play_compass(example_play_id)
ax.set_title(f'PlayKey: {p}')
plt.show()

f:id:bitop:20200101135931p:plain

Plays by max speed

trk.groupby('PlayKey')[['s']].max() \
    .sort_values('s', ascending=False) \
    .query('s != 0').head(20) \
    .plot(kind='barh', figsize=(15, 5), title='Top 20 Plays by Max Player Speed')
plt.show()

trk.groupby('PlayKey')[['s']].max() \
    .sort_values('s', ascending=True) \
    .query('s != 0').head(20) \
    .plot(kind='barh', figsize=(15, 5), title='Bottom 20 Plays by Min Player Speed')
plt.show()

f:id:bitop:20200101140034p:plain

Injury Length(怪我の治療にかかった長さ?)

inj[['DM_M1','DM_M7','DM_M28','DM_M42']].mean() \
    .plot(figsize=(15, 5),
          kind='bar',
          title='Percent of injuries by injury length')
plt.show()

f:id:bitop:20200101140124p:plain