Skip to content

Instantly share code, notes, and snippets.

@martinth
Created August 31, 2015 09:55
Show Gist options
  • Save martinth/c280b377d34fb0ab5c90 to your computer and use it in GitHub Desktop.
Save martinth/c280b377d34fb0ab5c90 to your computer and use it in GitHub Desktop.
Dota 2 winrates 6.84 pro and pub
Display the source blob
Display the rendered blob
Raw
{
"metadata": {
"name": "",
"signature": "sha256:06f9eda98d60c8fb159e3de5e02ff39bfb7c99b92176612b3b4990bc552508e0"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "code",
"collapsed": false,
"input": [
"from collections import namedtuple\n",
"import requests\n",
"from lxml.html import document_fromstring\n",
"\n",
"headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36'}\n",
"\n"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 23
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Get the data from dotabuff and parse it"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"db_tree = document_fromstring(requests.get('http://www.dotabuff.com/heroes/winning?date=patch_6.84', headers=headers).text)\n",
"db_data = {}\n",
"for node in db_tree.xpath(\"//a[@class='link-type-hero']\"):\n",
" name = node.text.lower().strip()\n",
" winrate = float(node.getparent().getparent()[2].text.strip('%')) / 100\n",
" db_data[name] = winrate\n",
"db_data.items()[:5]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 51,
"text": [
"[('naga siren', 0.441),\n",
" ('medusa', 0.5159),\n",
" ('undying', 0.6147),\n",
" ('riki', 0.5411),\n",
" ('tusk', 0.4961)]"
]
}
],
"prompt_number": 51
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Do the same for datdota"
]
},
{
"cell_type": "code",
"collapsed": true,
"input": [
"dd_tree = document_fromstring(requests.get('http://www.datdota.com/heroes.php?patch=11', headers=headers).text)\n",
"dd_data = {}\n",
"for node in dd_tree.xpath(\"//table/tbody\")[0].xpath('tr'):\n",
" name = node[1][0].text.lower().strip()\n",
" winrate = float(node[5].text)\n",
" dd_data[name] = winrate\n",
"dd_data.items()[:5]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 52,
"text": [
"[('naga siren', 0.571),\n",
" ('medusa', 0.273),\n",
" ('undying', 0.538),\n",
" ('riki', 0.0),\n",
" ('tusk', 0.571)]"
]
}
],
"prompt_number": 52
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Find out which hero name don't match up and fix that"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print 'Missing in datdota:', [hero for hero in db_data.keys() if hero not in dd_data]\n",
"print 'Missing in dotabuff:', [hero for hero in dd_data.keys() if hero not in db_data]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Missing in datdota: ['anti-mage', \"nature's prophet\", 'earth spirit', 'oracle']\n",
"Missing in dotabuff: ['natures prophet', 'anti mage']\n"
]
}
],
"prompt_number": 59
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def fix_name(hero_name):\n",
" return hero_name.replace(\"'\", '').replace('-', ' ')\n",
"\n",
"# these heros are not in captains draft and will be excluded\n",
"exclude = {'earth spirit', 'oracle'}\n",
"db_data = {fix_name(name): wr for name, wr in db_data.items() if name not in exclude}"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 64
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Combine the two sets into one list"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Herodata = namedtuple('Herodata', ['name', 'datdota', 'dotabuff', 'avg_winrate'])\n",
"\n",
"def avg_winrate(dd_wr, db_wr):\n",
" return (dd_wr + db_wr) / 2\n",
" \n",
"\n",
"data = [Herodata(name.title(), wr, db_data[name], avg_winrate(wr, db_data[name])) for name, wr in dd_data.items()]\n",
"data[:5]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 93,
"text": [
"[Herodata(name='Naga Siren', datdota=0.571, dotabuff=0.441, avg_winrate=0.506),\n",
" Herodata(name='Medusa', datdota=0.273, dotabuff=0.5159, avg_winrate=0.39445),\n",
" Herodata(name='Undying', datdota=0.538, dotabuff=0.6147, avg_winrate=0.57635),\n",
" Herodata(name='Riki', datdota=0.0, dotabuff=0.5411, avg_winrate=0.27055),\n",
" Herodata(name='Tusk', datdota=0.571, dotabuff=0.4961, avg_winrate=0.53355)]"
]
}
],
"prompt_number": 93
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Sort the heros by averaged winrate over pro and pubs"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"print 'Hero AVG Dotabuff Datdota\\n'\n",
"for item in sorted(data, key=lambda i: i.avg_winrate, reverse=True):\n",
" print '{name:<20} {avg_winrate:<8.2f} {dotabuff:<10.2f} {datdota:.2f} '.format(**item._asdict())"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Hero AVG Dotabuff Datdota\n",
"\n",
"Techies 0.63 0.51 0.75 \n",
"Omniknight 0.63 0.60 0.65 \n",
"Pudge 0.60 0.51 0.70 \n",
"Crystal Maiden 0.59 0.56 0.61 \n",
"Venomancer 0.58 0.53 0.64 \n",
"Elder Titan 0.58 0.49 0.67 \n",
"Undying 0.58 0.61 0.54 \n",
"Abaddon 0.57 0.58 0.56 \n",
"Pugna 0.57 0.49 0.65 \n",
"Leshrac 0.56 0.53 0.58 \n",
"Bounty Hunter 0.56 0.48 0.63 \n",
"Ursa 0.55 0.59 0.52 \n",
"Enigma 0.55 0.52 0.57 \n",
"Vengeful Spirit 0.55 0.53 0.56 \n",
"Juggernaut 0.55 0.49 0.60 \n",
"Templar Assassin 0.54 0.48 0.60 \n",
"Silencer 0.54 0.54 0.54 \n",
"Wraith King 0.54 0.56 0.52 \n",
"Beastmaster 0.54 0.50 0.57 \n",
"Spirit Breaker 0.53 0.55 0.52 \n",
"Tusk 0.53 0.50 0.57 \n",
"Treant Protector 0.53 0.51 0.56 \n",
"Dragon Knight 0.53 0.50 0.56 \n",
"Weaver 0.53 0.49 0.57 \n",
"Luna 0.53 0.53 0.53 \n",
"Clinkz 0.53 0.46 0.60 \n",
"Shadow Shaman 0.52 0.52 0.53 \n",
"Phantom Lancer 0.52 0.51 0.53 \n",
"Lifestealer 0.52 0.47 0.57 \n",
"Dazzle 0.52 0.53 0.51 \n",
"Slardar 0.52 0.54 0.49 \n",
"Disruptor 0.52 0.52 0.52 \n",
"Gyrocopter 0.51 0.52 0.51 \n",
"Visage 0.51 0.46 0.56 \n",
"Earthshaker 0.51 0.53 0.48 \n",
"Jakiro 0.51 0.55 0.46 \n",
"Viper 0.51 0.52 0.50 \n",
"Shadow Fiend 0.51 0.51 0.51 \n",
"Naga Siren 0.51 0.44 0.57 \n",
"Clockwerk 0.50 0.51 0.50 \n",
"Huskar 0.50 0.48 0.52 \n",
"Bloodseeker 0.50 0.54 0.46 \n",
"Night Stalker 0.50 0.51 0.49 \n",
"Drow Ranger 0.50 0.51 0.49 \n",
"Witch Doctor 0.50 0.53 0.46 \n",
"Tidehunter 0.50 0.51 0.48 \n",
"Centaur Warrunner 0.50 0.53 0.46 \n",
"Lycan 0.50 0.50 0.49 \n",
"Chen 0.50 0.44 0.55 \n",
"Queen Of Pain 0.49 0.48 0.51 \n",
"Dark Seer 0.49 0.51 0.48 \n",
"Lich 0.49 0.54 0.44 \n",
"Natures Prophet 0.49 0.44 0.53 \n",
"Storm Spirit 0.49 0.48 0.50 \n",
"Lion 0.49 0.48 0.49 \n",
"Winter Wyvern 0.49 0.48 0.49 \n",
"Morphling 0.49 0.42 0.55 \n",
"Keeper Of The Light 0.48 0.50 0.47 \n",
"Phantom Assassin 0.48 0.49 0.47 \n",
"Sven 0.48 0.52 0.44 \n",
"Brewmaster 0.48 0.49 0.47 \n",
"Zeus 0.48 0.57 0.39 \n",
"Windranger 0.48 0.48 0.48 \n",
"Broodmother 0.48 0.45 0.51 \n",
"Razor 0.48 0.49 0.47 \n",
"Spectre 0.48 0.55 0.40 \n",
"Mirana 0.47 0.52 0.43 \n",
"Bane 0.47 0.46 0.49 \n",
"Bristleback 0.47 0.48 0.47 \n",
"Ancient Apparition 0.47 0.49 0.46 \n",
"Terrorblade 0.47 0.44 0.50 \n",
"Legion Commander 0.47 0.48 0.46 \n",
"Slark 0.47 0.52 0.42 \n",
"Anti Mage 0.47 0.44 0.49 \n",
"Rubick 0.47 0.44 0.49 \n",
"Ogre Magi 0.47 0.52 0.41 \n",
"Axe 0.47 0.47 0.46 \n",
"Lina 0.47 0.48 0.45 \n",
"Tiny 0.46 0.49 0.44 \n",
"Io 0.46 0.41 0.50 \n",
"Nyx Assassin 0.45 0.47 0.44 \n",
"Ember Spirit 0.45 0.43 0.48 \n",
"Sand King 0.45 0.49 0.41 \n",
"Puck 0.45 0.43 0.47 \n",
"Enchantress 0.44 0.44 0.45 \n",
"Warlock 0.44 0.55 0.33 \n",
"Shadow Demon 0.43 0.42 0.44 \n",
"Kunkka 0.43 0.47 0.39 \n",
"Alchemist 0.43 0.40 0.47 \n",
"Timbersaw 0.43 0.45 0.41 \n",
"Batrider 0.43 0.40 0.46 \n",
"Magnus 0.43 0.45 0.40 \n",
"Faceless Void 0.42 0.47 0.38 \n",
"Phoenix 0.42 0.50 0.35 \n",
"Skywrath Mage 0.42 0.46 0.38 \n",
"Invoker 0.41 0.45 0.36 \n",
"Death Prophet 0.41 0.48 0.33 \n",
"Meepo 0.40 0.46 0.33 \n",
"Medusa 0.39 0.52 0.27 \n",
"Sniper 0.39 0.47 0.32 \n",
"Lone Druid 0.39 0.41 0.38 \n",
"Chaos Knight 0.39 0.53 0.25 \n",
"Tinker 0.37 0.44 0.30 \n",
"Troll Warlord 0.34 0.49 0.18 \n",
"Outworld Devourer 0.33 0.44 0.23 \n",
"Necrophos 0.29 0.57 0.00 \n",
"Doom 0.28 0.45 0.11 \n",
"Riki 0.27 0.54 0.00 \n"
]
}
],
"prompt_number": 94
},
{
"cell_type": "code",
"collapsed": false,
"input": [],
"language": "python",
"metadata": {},
"outputs": []
}
],
"metadata": {}
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment