In [288]:
%load_ext autoreload
%autoreload

import arrow
import json
import os

import requests
import pandas as pd
import seaborn as sns

import matplotlib.pyplot as plt
import numpy as np

from dota import api

In [5]:
# supply your own API key.
with open(os.path.expanduser('~/Dropbox/bin/api-keys.txt'), 'r') as f:
    api_keys = json.load(f)

KEY = api_keys['steam']  # just a string with the key.
account_id = "76561198025007092"

h = api.API(KEY)

In [7]:
history = h.get_match_history(account_id=account_id)
history.partner_counts().head()


Out[7]:
64741364     158
142531084     49
36947763       2
145551507      2
86047172       2
dtype: int64

In [8]:
details = history.get_all_match_details()


Added 550062218 (0.0%)
Added 541698504 (10.126582278481013%)
Added 533444058 (19.620253164556964%)
Added 533408126 (20.253164556962027%)
Added 525602243 (29.746835443037973%)
Added 525553478 (30.379746835443036%)
Added 510739148 (39.87341772151899%)
Added 480276736 (50.0%)
Added 471833055 (60.12658227848101%)
Added 466847536 (69.62025316455696%)
Added 466813579 (70.25316455696202%)
Added 459824629 (79.74683544303798%)
Added 459783808 (80.37974683544304%)
Added 453225946 (89.87341772151899%)

In [10]:
details[526809506].match_report()


Out[10]:
level kills deaths assists last_hits denies gold gold_spent player_slot account_id item_0 item_1 item_2 item_3 item_4 item_5 win
match_id team hero
526809506 Radiant witch_doctor 17 12 1 20 49 0 5044 9510 1 NaN 108 16 180 152 0 0 True
death_prophet 19 11 3 9 81 1 3326 12495 2 NaN 121 102 36 48 41 0 True
phantom_lancer 18 10 1 10 208 3 4162 17610 4 64741364 114 46 63 174 147 178 True
sand_king 15 3 3 21 56 1 1309 10220 3 142531084 180 108 73 1 0 0 True
110 18 12 1 22 24 3 3272 11145 0 102191207 114 92 102 0 214 0 True
Dire mirana 12 2 9 1 67 2 193 7235 128 87496722 0 168 0 0 0 0 False
shadow_shaman 12 0 11 4 63 2 730 7125 129 NaN 180 28 185 77 0 69 False
brewmaster 13 1 7 2 57 1 795 5480 132 NaN 50 81 16 182 60 0 False
medusa 11 1 7 2 54 2 687 6170 130 NaN 24 11 50 69 0 0 False
earthshaker 10 1 14 3 22 0 903 3580 131 NaN 44 182 38 180 92 0 False

10 rows × 17 columns


In [11]:
JOESID = 142531084
my_dota_id = api.id_32(int(account_id))
joes_steam = api.id_64(JOESID)

In [13]:
df = pd.concat([details[m].match_report() for m in details])
df.head()


Out[13]:
level kills deaths assists last_hits denies gold gold_spent player_slot account_id item_0 item_1 item_2 item_3 item_4 item_5 win
match_id team hero
480276736 Radiant riki 25 13 11 18 89 0 1479 13961 1 NaN 147 63 125 154 0 0 False
sniper 25 17 9 13 299 20 1726 25140 2 122320847 63 116 168 154 141 164 False
crystal_maiden 19 4 18 9 78 0 359 11570 3 70170480 79 21 214 8 1 26 False
lone_druid 25 7 8 14 293 3 1029 21054 0 64741364 36 214 0 0 182 43 False
shredder 25 9 12 11 236 2 3752 19594 4 65048379 152 180 121 116 168 30 False

5 rows × 17 columns


In [14]:
# my win percent
df[df.account_id == my_dota_id].win.mean()


Out[14]:
0.57594936708860756

In [16]:
# Win percent with Joe
df[df.account_id == JOESID].win.mean()


Out[16]:
0.53061224489795922

In [17]:
gr = df.groupby(level='match_id')
games = gr['account_id'].apply(lambda x:
                              (my_dota_id in x.values) &
                              (JOESID in x.values))
games = games[games].index

idx_names =  df.index.names
df = df.reset_index()
joint = df[df.match_id.isin(games)]
joint = joint.set_index(idx_names)
df = df.set_index(idx_names)

joint.head()


Out[17]:
level kills deaths assists last_hits denies gold gold_spent player_slot account_id item_0 item_1 item_2 item_3 item_4 item_5 win
match_id team hero
546195205 Radiant omniknight 18 3 7 10 49 23 3564 9005 2 NaN 180 79 178 9 0 0 True
weaver 20 8 7 15 142 6 4621 15030 3 142531084 63 212 168 32 123 30 True
spectre 21 4 12 17 111 4 1673 16075 0 126801707 50 11 114 65 127 0 True
windrunner 22 11 5 16 160 3 4422 17385 1 NaN 152 7 7 141 164 63 True
viper 21 6 6 12 178 15 3530 16935 4 64741364 50 46 185 108 52 116 True

5 rows × 17 columns


In [18]:
joint.win.mean()


Out[18]:
0.5

In [20]:
import datetime

df.to_csv('../data/details_joined-' + datetime.datetime.now().strftime('%Y-%m-%d'))

In [21]:
for k, v in details.items():
    with open('../data/detail' + str(k) + '.json', 'w') as f:
        json.dump(v.resp, f)

In [24]:
# Joe's data

steam_id = api.id_64(142531084)
joe_hist = h.get_match_history(account_id=steam_id)
details = joe_hist.get_all_match_details()


Added 550037822 (0.0%)
Added 550014092 (0.2%)
Added 548780514 (0.4%)
Added 530054192 (9.6%)
Added 530034680 (9.8%)
Added 528314084 (10.0%)
Added 528276599 (10.2%)
Added 526978510 (10.4%)
Added 494192603 (19.6%)
Added 492408049 (19.8%)
Added 490424342 (20.0%)
Added 488885955 (20.2%)
Added 487444215 (20.4%)
Added 468071052 (29.6%)
Added 467640267 (29.8%)
Added 466847536 (30.0%)
Added 466813579 (30.2%)
Added 466787253 (30.4%)
Added 453662179 (39.6%)
Added 453659416 (39.8%)
Added 453626436 (40.0%)
Added 453424938 (40.2%)
Added 453346070 (40.4%)
Added 434674901 (49.6%)
Added 433379320 (49.8%)
Added 433317133 (50.0%)
Added 433210652 (50.2%)
Added 433123686 (50.4%)
Added 418395806 (59.6%)
Added 417495200 (59.8%)
Added 417421662 (60.0%)
Added 417373757 (60.2%)
Added 417337096 (60.4%)
Added 402121381 (69.6%)
Added 402097237 (69.8%)
Added 402044535 (70.0%)
Added 402016353 (70.2%)
Added 401111775 (70.4%)
Added 385699276 (79.6%)
Added 385523515 (79.8%)
Added 385511908 (80.0%)
Added 385454704 (80.2%)
Added 383925673 (80.4%)
Added 368991886 (89.6%)
Added 368925474 (89.8%)
Added 367903256 (90.0%)
Added 367839135 (90.2%)
Added 367830558 (90.4%)
Added 354222605 (99.6%)
Added 354220703 (99.8%)

In [41]:
df = details[max(details)].match_report()
df


Out[41]:
level kills deaths assists last_hits denies gold gold_spent player_slot account_id item_0 item_1 item_2 item_3 item_4 item_5 win
match_id team hero
550037822 Radiant phantom_assassin 22 18 3 14 98 8 2941 17615 2 142531084 145 112 0 50 135 0 True
leshrac 20 9 6 20 122 0 3930 16245 3 NaN 36 121 108 48 185 0 True
spirit_breaker 20 16 4 17 97 5 3905 14585 4 NaN 63 172 92 141 108 0 True
silencer 16 4 4 10 66 3 4045 10560 0 NaN 102 36 206 79 63 77 True
102 15 4 5 17 18 4 2841 9100 1 64741364 180 36 102 46 185 0 True
Dire pudge 12 6 7 4 15 4 698 6170 129 NaN 1 41 180 43 46 42 False
kunkka 12 2 10 5 64 3 498 5500 130 149474577 92 50 36 5 73 46 False
sniper 16 6 9 10 83 1 934 9975 132 NaN 212 63 166 168 0 0 False
warlock 11 0 13 10 26 3 1149 3745 131 NaN 180 16 16 42 60 0 False
antimage 15 4 14 5 116 1 499 8830 128 NaN 11 145 21 71 63 46 False

10 rows × 17 columns


In [31]:
for k, v in details.items():
    with open('../data/detail' + str(k) + '.json', 'w') as f:
        json.dump(v.resp, f)

In [32]:
len(details)


Out[32]:
500

In [39]:
df


Out[39]:
level kills deaths assists last_hits denies gold gold_spent player_slot account_id item_0 item_1 item_2 item_3 item_4 item_5 win
match_id team hero
480276736 Radiant riki 25 13 11 18 89 0 1479 13961 1 NaN 147 63 125 154 0 0 False
sniper 25 17 9 13 299 20 1726 25140 2 122320847 63 116 168 154 141 164 False
crystal_maiden 19 4 18 9 78 0 359 11570 3 70170480 79 21 214 8 1 26 False
lone_druid 25 7 8 14 293 3 1029 21054 0 64741364 36 214 0 0 182 43 False
shredder 25 9 12 11 236 2 3752 19594 4 65048379 152 180 121 116 168 30 False
Dire mirana 25 8 9 11 172 3 1157 19374 128 148260268 63 212 123 168 139 46 True
kunkka 25 11 8 22 325 5 1202 30944 130 85520638 135 48 152 114 141 112 True
lion 18 0 22 7 34 0 3157 5765 132 NaN 180 73 214 170 41 30 True
dragon_knight 25 20 7 14 283 0 1264 28334 131 102876437 112 48 114 151 141 40 True
bloodseeker 25 19 6 7 214 3 995 29985 129 NaN 48 208 0 154 53 139 True
544028929 Radiant viper 25 16 5 14 235 11 2562 25315 0 64741364 50 79 135 32 108 10 True
zuus 20 5 12 16 91 1 2092 10595 1 NaN 73 108 42 46 69 29 True
lone_druid 25 7 6 19 214 1 1595 25625 3 NaN 125 139 50 81 143 0 True
rubick 20 2 11 19 57 4 2000 12560 2 NaN 102 180 100 88 108 0 True
juggernaut 25 16 9 15 265 0 1406 24800 4 NaN 208 50 139 8 108 145 True
Dire 110 21 3 9 16 152 5 829 12415 128 NaN 79 127 56 137 214 0 False
storm_spirit 25 13 7 14 173 6 322 20375 131 NaN 121 63 123 8 98 21 False
tinker 20 6 9 14 131 0 212 16760 132 NaN 178 48 41 96 102 23 False
clinkz 24 10 10 11 157 9 1346 18765 129 NaN 98 212 63 160 51 149 False
axe 20 10 11 11 131 0 393 19060 130 NaN 214 114 1 127 90 0 False
546195205 Radiant omniknight 18 3 7 10 49 23 3564 9005 2 NaN 180 79 178 9 0 0 True
weaver 20 8 7 15 142 6 4621 15030 3 142531084 63 212 168 32 123 30 True
spectre 21 4 12 17 111 4 1673 16075 0 126801707 50 11 114 65 127 0 True
windrunner 22 11 5 16 160 3 4422 17385 1 NaN 152 7 7 141 164 63 True
viper 21 6 6 12 178 15 3530 16935 4 64741364 50 46 185 108 52 116 True
Dire mirana 18 4 9 8 99 0 135 13500 129 NaN 63 170 212 168 172 149 False
nevermore 23 6 7 7 328 14 962 19165 131 136896429 63 147 1 116 164 149 False
riki 25 23 2 5 172 7 1555 22805 132 NaN 196 50 147 61 139 81 False
shadow_demon 15 0 9 7 39 1 601 9485 130 NaN 180 104 41 100 37 0 False
rubick 17 2 8 9 31 2 391 10160 128 NaN 180 79 23 60 21 46 False
541670151 Radiant shredder 23 9 8 9 139 7 1306 11775 0 64741364 182 46 53 180 121 0 False
razor 20 9 11 12 113 1 488 9580 1 NaN 50 41 154 170 212 0 False
slardar 19 3 12 13 78 0 1661 9325 3 NaN 11 1 8 73 125 63 False
venomancer 19 15 12 19 76 8 363 14115 4 NaN 100 0 108 212 63 102 False
crystal_maiden 13 1 16 6 43 0 300 4780 2 NaN 29 79 40 0 16 0 False
Dire furion 25 17 5 20 257 0 5753 23160 130 NaN 164 214 152 141 108 135 True
drow_ranger 23 13 6 12 177 13 9401 14075 128 NaN 0 152 63 149 212 116 True
pudge 19 2 13 19 43 0 1172 11425 132 NaN 50 90 0 108 0 0 True
jakiro 20 9 5 18 45 2 787 14735 129 NaN 180 108 46 79 131 31 True
lion 20 15 13 12 41 1 1138 13875 131 NaN 202 1 60 22 23 214 True
539074056 Radiant furion 25 8 9 11 327 1 3805 20745 4 NaN 63 168 98 147 152 0 False
windrunner 20 10 9 7 92 3 504 11945 2 NaN 36 0 46 50 96 102 False
necrolyte 18 4 11 10 132 0 555 12735 0 NaN 36 79 201 108 0 63 False
disruptor 16 4 14 13 42 0 665 8280 3 NaN 9 0 102 79 180 0 False
venomancer 14 2 14 18 86 0 449 10865 1 64741364 36 31 102 46 29 88 False
Dire tiny 23 14 6 20 182 13 5586 19290 130 119076832 108 48 0 46 158 170 True
enigma 20 7 9 12 148 10 3225 15695 128 117192154 180 116 79 1 106 46 True
ancient_apparition 19 9 6 23 57 3 3128 12520 132 NaN 90 180 34 193 40 46 True
doom_bringer 25 16 5 25 248 6 5731 22265 131 19668635 46 114 137 50 112 125 True
110 24 8 3 27 151 8 3470 17500 129 54088949 114 214 119 92 30 48 True
536456564 Radiant lion 14 5 11 4 30 4 174 6950 3 NaN 214 77 108 0 0 0 False
bristleback 15 4 9 2 75 6 195 6975 0 NaN 127 125 0 16 16 63 False
viper 20 11 12 8 104 3 1414 8875 2 125067608 0 108 41 36 50 40 False
doom_bringer 16 2 9 4 136 1 71 13345 1 120070849 65 88 152 50 185 9 False
faceless_void 16 2 5 8 109 4 390 10035 4 NaN 11 172 63 145 182 3 False
Dire antimage 18 6 4 8 52 4 391 12175 132 NaN 71 81 63 170 52 10 True
drow_ranger 19 6 8 10 113 6 679 16580 130 109009600 63 36 152 154 26 141 True
vengefulspirit 21 10 4 16 42 3 1864 13880 129 142531084 168 212 48 102 40 36 True
nyx_assassin 19 11 6 17 27 0 328 13560 128 64741364 41 0 203 46 180 92 True
furion 23 12 2 18 295 12 9497 20385 131 NaN 152 65 63 108 168 135 True
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...

1580 rows × 17 columns


In [199]:
dfj = pd.concat([x.match_report() for x in details.values()])

In [254]:
win_pct = dfj.groupby(level='hero').win.mean()
colors = plt.cm.OrRd(win_pct)
hero_counts = dfj.query('account_id == @JOESID').groupby(level='hero').size()
hero_counts.sort()
fig, ax = plt.subplots(figsize=(20, 10))
hero_counts.plot(kind='barh', ax=ax, color=colors)
ax.grid()



In [271]:
idx = hero_counts.index & win_pct.index
fig, ax = plt.subplots()
ax.scatter(hero_counts[idx], win_pct[idx])
ax.set_ylim(0, 1)
ax.set_xlim(0)


Out[271]:
(0, 70.0)

In [274]:
dfj.head()


Out[274]:
level kills deaths assists last_hits denies gold gold_spent player_slot account_id item_0 item_1 item_2 item_3 item_4 item_5 win
match_id team hero
378160128 Radiant alchemist 20 6 8 16 172 10 4365 18108 1 NaN 94 143 152 100 63 137 True
jakiro 17 1 6 19 50 2 2870 9960 0 NaN 180 36 79 102 44 190 True
keeper_of_the_light 17 0 2 11 75 4 1886 11101 3 NaN 79 100 102 185 0 214 True
centaur 18 6 3 11 143 12 2407 16125 4 NaN 90 36 125 29 137 0 True
101 22 17 2 7 110 10 928 19943 2 142531084 121 48 108 206 58 0 True

5 rows × 17 columns


In [278]:
dfj.plot?

In [287]:
ax = dfj.plot(kind='hexbin', x='kills', y='assists', gridsize=20)
ax.set_xlim(0, 30)
ax.set_ylim(0, 30)


Out[287]:
(0, 30)

In [291]:
details[ 459675819 ].to_json()


---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-291-5c5b63d2c7a7> in <module>()
----> 1 details[ 459675819 ].to_json()

AttributeError: 'DetailsResponse' object has no attribute 'to_json'