In [1]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

plt.style.use('ggplot')
In [2]:
hero_stats = pd.read_csv('hero_play_stats.csv')
In [3]:
hero_stats
Out[3]:
hero total_games_daily guide_games_daily adj_guide_games_daily
0 Abaddon 22149.3444 5897.500000 5012.875000
1 Alchemist 65124.3672 14445.714290 12278.857140
2 Ancient Apparition 48181.4424 9665.158730 8215.384921
3 Anti-Mage 137043.5532 21790.507940 18521.931750
4 Arc Warden 21972.8556 6236.746032 5301.234127
5 Axe 209580.4500 27661.658730 23512.409920
6 Bane 45357.6216 5932.904762 5042.969048
7 Batrider 7941.9960 3653.809524 3105.738095
8 Beastmaster 6530.0856 4317.785714 3670.117857
9 Bloodseeker 132896.0664 29368.769840 24963.454370
10 Bounty Hunter 74831.2512 8565.404762 7280.594048
11 Brewmaster 35297.7600 5575.801587 4739.431349
12 Bristleback 128395.6020 25966.944440 22071.902780
13 Broodmother 24355.4544 7413.095238 6301.130952
14 Centaur Warrunner 76507.8948 11028.182540 9373.955159
15 Chaos Knight 89038.5996 15049.277780 12791.886110
16 Chen 4323.9756 1534.261905 1304.122619
17 Clinkz 83479.2024 19311.880950 16415.098810
18 Clockwerk 32562.1836 6975.452381 5929.134524
19 Crystal Maiden 129454.5348 22962.674600 19518.273410
20 Dark Seer 24620.1876 3878.547619 3296.765476
21 Dark Willow 48799.1532 10587.539680 8999.408730
22 Dazzle 39621.7356 6646.738095 5649.727381
23 Death Prophet 11118.7944 4831.690476 4106.936905
24 Disruptor 32650.4280 7346.142857 6244.221429
25 Doom 27885.2304 8563.555556 7279.022222
26 Dragon Knight 48975.6420 12020.801590 10217.681350
27 Drow Ranger 123806.8932 28877.333330 24545.733330
28 Earth Spirit 17295.9024 5040.690476 4284.586905
29 Earthshaker 214963.3584 25812.428570 21940.564290
... ... ... ... ...
86 Slark 101128.0824 22062.087300 18752.774210
87 Sniper 226170.3972 39068.746030 33208.434130
88 Spectre 91509.4428 24314.896830 20667.662300
89 Spirit Breaker 119041.6956 17503.349210 14877.846830
90 Storm Spirit 152221.5900 27047.246030 22990.159130
91 Sven 70066.0536 13934.968250 11844.723020
92 Techies 47298.9984 6549.063492 5566.703968
93 Templar Assassin 31238.5176 10464.373020 8894.717063
94 Terrorblade 65653.8336 10902.769840 9267.354365
95 Tidehunter 46769.5320 7238.730159 6152.920635
96 Timbersaw 32826.9168 7936.579365 6746.092460
97 Tinker 132631.3332 19372.579370 16466.692460
98 Tiny 57182.3712 12738.380950 10827.623810
99 Treant Protector 39180.5136 6501.761905 5526.497619
100 Troll Warlord 77566.8276 14594.912700 12405.675790
101 Tusk 37062.6480 7368.571429 6263.285714
102 Underlord 38298.0696 7601.357143 6461.153571
103 Undying 52417.1736 8041.198413 6835.018651
104 Ursa 129454.5348 19408.753970 16497.440870
105 Vengeful Spirit 69713.0760 21118.269840 17950.529370
106 Venomancer 46063.5768 7695.738095 6541.377381
107 Viper 63800.7012 16191.539680 13762.808730
108 Visage 11118.7944 2855.301587 2427.006349
109 Warlock 37239.1368 9651.492063 8203.768254
110 Weaver 108099.3900 21308.817460 18112.494840
111 Windranger 150015.4800 31550.785710 26818.167860
112 Winter Wyvern 48093.1980 8136.515873 6916.038492
113 Witch Doctor 64241.9232 13649.563490 11602.128970
114 Wraith King 95480.4408 20484.206350 17411.575400
115 Zeus 168017.3376 29345.642860 24943.796430

116 rows × 4 columns

In [4]:
hero_stats['total_games_daily'] = np.ceil(hero_stats['total_games_daily'])
In [5]:
hero_stats['adj_guide_games_daily'] = np.ceil(hero_stats['adj_guide_games_daily'])
In [6]:
hero_stats['adj_guide_games_daily'].sum() / hero_stats['total_games_daily'].sum()
Out[6]:
0.15934834334877587
In [7]:
hero_stats['total_games_pct'] = hero_stats['total_games_daily'] / hero_stats['total_games_daily'].sum()
In [8]:
hero_stats['guide_games_pct'] = hero_stats['adj_guide_games_daily'] / hero_stats['total_games_daily']
In [9]:
hero_stats
Out[9]:
hero total_games_daily guide_games_daily adj_guide_games_daily total_games_pct guide_games_pct
0 Abaddon 22150.0 5897.500000 5013.0 0.002511 0.226321
1 Alchemist 65125.0 14445.714290 12279.0 0.007382 0.188545
2 Ancient Apparition 48182.0 9665.158730 8216.0 0.005461 0.170520
3 Anti-Mage 137044.0 21790.507940 18522.0 0.015534 0.135154
4 Arc Warden 21973.0 6236.746032 5302.0 0.002491 0.241296
5 Axe 209581.0 27661.658730 23513.0 0.023756 0.112191
6 Bane 45358.0 5932.904762 5043.0 0.005141 0.111182
7 Batrider 7942.0 3653.809524 3106.0 0.000900 0.391085
8 Beastmaster 6531.0 4317.785714 3671.0 0.000740 0.562089
9 Bloodseeker 132897.0 29368.769840 24964.0 0.015064 0.187845
10 Bounty Hunter 74832.0 8565.404762 7281.0 0.008482 0.097298
11 Brewmaster 35298.0 5575.801587 4740.0 0.004001 0.134285
12 Bristleback 128396.0 25966.944440 22072.0 0.014553 0.171906
13 Broodmother 24356.0 7413.095238 6302.0 0.002761 0.258745
14 Centaur Warrunner 76508.0 11028.182540 9374.0 0.008672 0.122523
15 Chaos Knight 89039.0 15049.277780 12792.0 0.010092 0.143667
16 Chen 4324.0 1534.261905 1305.0 0.000490 0.301804
17 Clinkz 83480.0 19311.880950 16416.0 0.009462 0.196646
18 Clockwerk 32563.0 6975.452381 5930.0 0.003691 0.182109
19 Crystal Maiden 129455.0 22962.674600 19519.0 0.014673 0.150778
20 Dark Seer 24621.0 3878.547619 3297.0 0.002791 0.133910
21 Dark Willow 48800.0 10587.539680 9000.0 0.005531 0.184426
22 Dazzle 39622.0 6646.738095 5650.0 0.004491 0.142598
23 Death Prophet 11119.0 4831.690476 4107.0 0.001260 0.369368
24 Disruptor 32651.0 7346.142857 6245.0 0.003701 0.191265
25 Doom 27886.0 8563.555556 7280.0 0.003161 0.261063
26 Dragon Knight 48976.0 12020.801590 10218.0 0.005551 0.208633
27 Drow Ranger 123807.0 28877.333330 24546.0 0.014033 0.198260
28 Earth Spirit 17296.0 5040.690476 4285.0 0.001960 0.247745
29 Earthshaker 214964.0 25812.428570 21941.0 0.024366 0.102068
... ... ... ... ... ... ...
86 Slark 101129.0 22062.087300 18753.0 0.011463 0.185436
87 Sniper 226171.0 39068.746030 33209.0 0.025636 0.146831
88 Spectre 91510.0 24314.896830 20668.0 0.010372 0.225855
89 Spirit Breaker 119042.0 17503.349210 14878.0 0.013493 0.124981
90 Storm Spirit 152222.0 27047.246030 22991.0 0.017254 0.151036
91 Sven 70067.0 13934.968250 11845.0 0.007942 0.169052
92 Techies 47299.0 6549.063492 5567.0 0.005361 0.117698
93 Templar Assassin 31239.0 10464.373020 8895.0 0.003541 0.284740
94 Terrorblade 65654.0 10902.769840 9268.0 0.007442 0.141164
95 Tidehunter 46770.0 7238.730159 6153.0 0.005301 0.131559
96 Timbersaw 32827.0 7936.579365 6747.0 0.003721 0.205532
97 Tinker 132632.0 19372.579370 16467.0 0.015034 0.124156
98 Tiny 57183.0 12738.380950 10828.0 0.006482 0.189357
99 Treant Protector 39181.0 6501.761905 5527.0 0.004441 0.141063
100 Troll Warlord 77567.0 14594.912700 12406.0 0.008792 0.159939
101 Tusk 37063.0 7368.571429 6264.0 0.004201 0.169010
102 Underlord 38299.0 7601.357143 6462.0 0.004341 0.168725
103 Undying 52418.0 8041.198413 6836.0 0.005941 0.130413
104 Ursa 129455.0 19408.753970 16498.0 0.014673 0.127442
105 Vengeful Spirit 69714.0 21118.269840 17951.0 0.007902 0.257495
106 Venomancer 46064.0 7695.738095 6542.0 0.005221 0.142020
107 Viper 63801.0 16191.539680 13763.0 0.007232 0.215718
108 Visage 11119.0 2855.301587 2428.0 0.001260 0.218365
109 Warlock 37240.0 9651.492063 8204.0 0.004221 0.220301
110 Weaver 108100.0 21308.817460 18113.0 0.012253 0.167558
111 Windranger 150016.0 31550.785710 26819.0 0.017004 0.178774
112 Winter Wyvern 48094.0 8136.515873 6917.0 0.005451 0.143823
113 Witch Doctor 64242.0 13649.563490 11603.0 0.007282 0.180614
114 Wraith King 95481.0 20484.206350 17412.0 0.010823 0.182361
115 Zeus 168018.0 29345.642860 24944.0 0.019045 0.148460

116 rows × 6 columns

In [10]:
team_temp = hero_stats.sample(10, weights='total_games_pct')
In [11]:
team_temp['prob'] = np.random.rand(10)
In [12]:
team_temp
Out[12]:
hero total_games_daily guide_games_daily adj_guide_games_daily total_games_pct guide_games_pct prob
69 Phantom Assassin 228377.0 35586.507940 30249.0 0.025886 0.132452 0.409369
114 Wraith King 95481.0 20484.206350 17412.0 0.010823 0.182361 0.376970
42 Keeper of the Light 28415.0 6306.325397 5361.0 0.003221 0.188668 0.131465
49 Lion 119130.0 22220.103170 18888.0 0.013503 0.158549 0.503390
58 Morphling 72184.0 11758.952380 9996.0 0.008182 0.138479 0.090295
71 Phoenix 88951.0 12461.484130 10593.0 0.010082 0.119088 0.310298
41 Juggernaut 146221.0 30924.611110 26286.0 0.016574 0.179769 0.646978
24 Disruptor 32651.0 7346.142857 6245.0 0.003701 0.191265 0.787482
26 Dragon Knight 48976.0 12020.801590 10218.0 0.005551 0.208633 0.848636
70 Phantom Lancer 91951.0 22080.222220 18769.0 0.010422 0.204120 0.822573
In [13]:
(team_temp['prob'] < team_temp['guide_games_pct']).sum()
Out[13]:
2
In [14]:
ttl_guide_counts = dict()
for i in range(100000):
    team_temp = hero_stats.sample(10, weights='total_games_pct')
    team_temp['prob'] = np.random.rand(10)
    ttl_count = (team_temp['prob'] < team_temp['guide_games_pct']).sum()
    ttl_guide_counts[ttl_count] = ttl_guide_counts.get(ttl_count, 0) + 1
In [15]:
ttl_guide_counts
Out[15]:
{0: 17327, 1: 33191, 2: 28731, 3: 14582, 4: 4909, 5: 1058, 6: 183, 7: 19}
In [18]:
x, y = zip(*sorted(ttl_guide_counts.items()))
y = [n/100000. for n in y]
In [19]:
plt.figure(figsize=(12,9))
plt.title('Monte Carlo Simulation of Torte de Lini Guides Used in a Game', fontsize=24)
plt.xlabel('Number of Torte de Lini Guides Used in a Game', fontsize=18)
plt.ylabel('Percent', fontsize=18)      
plt.bar(x, y)
for i, v in enumerate(y):
    plt.text(i-.22, v+.005, str(round((v*100), 4)) + '%', fontweight='bold')

Process Methodology

Given that we know that how many games are played daily, how many games are played for each hero, and how many games for a specific hero use a Torte de Lini guide by day, we can then get an estimate of how many games have at least one person using a Torte de Lini guide.

This was calculated by using a Monte Carlo simulation method. While it could theoretically be calculated to exact precision given that we have the percents, there are a possible 81,572,506,886,508 possible team combinations, which is an unrealistic amount of calculations required for very little upside. The Monte Carlo simulation created teams of 10 different heroes, based on play rate and calculated the probability of that person using a guide given the numbers provided. This was then run 100,000 times and stored. Across multiple tests, the percents were fairly stable.

So the Monte Carlo simulation shows that roughly 17% of games have no one in the game using a guide, but in the other 83%, at least 1 person uses a guide, which is a pretty remarkable number.

To semi-validate this data, given the numbers we have, it seems like roughly 15% of all games use a Torte de Lini guide, which means that 85% of games do not. If we take that basic assumption given all heroes are picked equally, the probability of a game having no one using a guide is .85 ^ 10 or 19.68%. Not too far off from what our Monte Carlo simulation shows, so the results look fairly reasonable. So even though only 15% of games played on any individual hero us a Torte de Lini guide, the combined probability of among 10 people, at least 1 person using a guide is around 83%.

Some assumptions are made that are not representative of the real world. Heroes were selected at random, whereas more realistically, you would assume some level of team composition. There is also the assumption that players will use guides at random, whereas the truth is probably less skilled players use guides more often than skilled players. So realistically, more than 17% of games will have no one using a guide, but there is no better way to calculate this skill based guide usage.