Background: Os dados usados neste notebook foram coletados em https://www.hltv.org/results. Foi raspado usando as bibliotecas 'requests' e 'BeautifulSoup'.
O Counter Strike Global Offensive, também conhecido como CS:GO, é um jogo de tiro em primeira pessoa (FPS) em que duas equipes, os terroristas e os contra-terroristas, se enfrentam em uma série de rodadas. Cada rodada tem um objetivo diferente, como plantar ou desarmar uma bomba, resgatar reféns ou eliminar toda a equipe adversária.
Os jogadores começam cada rodada com uma quantia limitada de dinheiro, que podem ser usados para comprar armas, equipamentos e granadas. As armas variam em termos de dano, alcance e cadência de tiro, e as granadas têm diferentes efeitos, como cegar os adversários, bloquear áreas ou causar dano.
Além disso, os jogadores podem comprar coletes e capacetes, que reduzem o dano que recebem, e kits de desativação de bomba, que aceleram o processo de desativação da bomba. O objetivo dos terroristas varia dependendo do mapa, mas geralmente envolve plantar uma bomba em um dos pontos de bomba disponíveis no mapa. Os contra-terroristas devem impedir que isso aconteça, desarmar a bomba caso ela seja plantada ou eliminar todos os terroristas antes que eles tenham a chance de plantar a bomba.
Já o objetivo dos contra-terroristas pode variar entre resgatar reféns, proteger áreas do mapa ou simplesmente eliminar todos os terroristas. O jogo é jogado em rodadas, e cada rodada tem uma duração máxima de dois minutos. A equipe vencedora de uma rodada ganha dinheiro extra, enquanto a equipe perdedora ganha menos dinheiro. Os jogadores também podem ganhar dinheiro ao completar objetivos ou matar inimigos.
No final de cada rodada, os jogadores podem usar o dinheiro ganho para comprar mais equipamentos, melhorar suas armas ou salvar dinheiro para rodadas futuras.
Importando bibliotecas e carregando as tabelas.
import numpy as np
import pandas as pd
import plotly.graph_objects as go
import plotly.express as px
from os import listdir
pd.set_option('display.max_columns',100)
listdir('C:\\Users\\PC4\\Jupyter\\csgo-professional-matches\\')
['economy.csv', 'picks.csv', 'players.csv', 'results.csv']
base_dir = 'C:\\Users\\PC4\\Jupyter\\csgo-professional-matches\\'
results_df = pd.read_csv(base_dir+'results.csv',low_memory=False)
picks_df = pd.read_csv(base_dir+'picks.csv',low_memory=False)
economy_df = pd.read_csv(base_dir+'economy.csv',low_memory=False)
players_df = pd.read_csv(base_dir+'players.csv',low_memory=False)
As primeiras linhas de cada tabela são apresentadas a seguir. Os dados são divididos em 4 tabelas que armazenam dados relacionados a:
results_df: pontuações do mapa e classificação das equipes;
picks_df: ordem de picks e vetos no processo de seleção de mapas;
economic_df: valor do equipamento inicial da rodada para todas as rodadas jogadas;
players_df: performances individuais dos jogadores em cada mapa.
Os valores armazenados nas colunas 'event_id' e 'match_id' são exclusivos para cada correspondência e evento e compartilhados entre dataframes, portanto, essas colunas podem ser usadas como chaves para mesclar dados entre dataframes.
É necessário observar que as linhas em 'results_df' e 'economy_df' armazenam dados para cada mapa jogado em uma partida, enquanto as linhas em 'picks_df' e 'players_df' armazenam dados para toda a partida.
results_df.head()
date | team_1 | team_2 | _map | result_1 | result_2 | map_winner | starting_ct | ct_1 | t_2 | t_1 | ct_2 | event_id | match_id | rank_1 | rank_2 | map_wins_1 | map_wins_2 | match_winner | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2020-03-18 | Recon 5 | TeamOne | Dust2 | 0 | 16 | 2 | 2 | 0 | 1 | 0 | 15 | 5151 | 2340454 | 62 | 63 | 0 | 2 | 2 |
1 | 2020-03-18 | Recon 5 | TeamOne | Inferno | 13 | 16 | 2 | 2 | 8 | 6 | 5 | 10 | 5151 | 2340454 | 62 | 63 | 0 | 2 | 2 |
2 | 2020-03-18 | New England Whalers | Station7 | Inferno | 12 | 16 | 2 | 1 | 9 | 6 | 3 | 10 | 5243 | 2340461 | 140 | 118 | 12 | 16 | 2 |
3 | 2020-03-18 | Rugratz | Bad News Bears | Inferno | 7 | 16 | 2 | 2 | 0 | 8 | 7 | 8 | 5151 | 2340453 | 61 | 38 | 0 | 2 | 2 |
4 | 2020-03-18 | Rugratz | Bad News Bears | Vertigo | 8 | 16 | 2 | 2 | 4 | 5 | 4 | 11 | 5151 | 2340453 | 61 | 38 | 0 | 2 | 2 |
picks_df.head()
date | team_1 | team_2 | inverted_teams | match_id | event_id | best_of | system | t1_removed_1 | t1_removed_2 | t1_removed_3 | t2_removed_1 | t2_removed_2 | t2_removed_3 | t1_picked_1 | t2_picked_1 | left_over | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2020-03-18 | TeamOne | Recon 5 | 1 | 2340454 | 5151 | 3 | 123412 | Vertigo | Train | 0.0 | Nuke | Overpass | 0.0 | Dust2 | Inferno | Mirage |
1 | 2020-03-18 | Rugratz | Bad News Bears | 0 | 2340453 | 5151 | 3 | 123412 | Dust2 | Nuke | 0.0 | Mirage | Train | 0.0 | Vertigo | Inferno | Overpass |
2 | 2020-03-18 | New England Whalers | Station7 | 0 | 2340461 | 5243 | 1 | 121212 | Mirage | Dust2 | Vertigo | Nuke | Train | Overpass | 0.0 | 0.0 | Inferno |
3 | 2020-03-17 | Complexity | forZe | 1 | 2340279 | 5226 | 3 | 123412 | Inferno | Nuke | 0.0 | Overpass | Vertigo | 0.0 | Dust2 | Train | Mirage |
4 | 2020-03-17 | Singularity | Endpoint | 0 | 2340456 | 5247 | 3 | 123412 | Train | Mirage | 0.0 | Nuke | Inferno | 0.0 | Overpass | Vertigo | Dust2 |
economy_df.head()
date | match_id | event_id | team_1 | team_2 | best_of | _map | t1_start | t2_start | 1_t1 | 2_t1 | 3_t1 | 4_t1 | 5_t1 | 6_t1 | 7_t1 | 8_t1 | 9_t1 | 10_t1 | 11_t1 | 12_t1 | 13_t1 | 14_t1 | 15_t1 | 16_t1 | 17_t1 | 18_t1 | 19_t1 | 20_t1 | 21_t1 | 22_t1 | 23_t1 | 24_t1 | 25_t1 | 26_t1 | 27_t1 | 28_t1 | 29_t1 | 30_t1 | 1_t2 | 2_t2 | 3_t2 | 4_t2 | 5_t2 | 6_t2 | 7_t2 | 8_t2 | 9_t2 | 10_t2 | 11_t2 | 12_t2 | 13_t2 | 14_t2 | 15_t2 | 16_t2 | 17_t2 | 18_t2 | 19_t2 | 20_t2 | 21_t2 | 22_t2 | 23_t2 | 24_t2 | 25_t2 | 26_t2 | 27_t2 | 28_t2 | 29_t2 | 30_t2 | 1_winner | 2_winner | 3_winner | 4_winner | 5_winner | 6_winner | 7_winner | 8_winner | 9_winner | 10_winner | 11_winner | 12_winner | 13_winner | 14_winner | 15_winner | 16_winner | 17_winner | 18_winner | 19_winner | 20_winner | 21_winner | 22_winner | 23_winner | 24_winner | 25_winner | 26_winner | 27_winner | 28_winner | 29_winner | 30_winner | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2020-03-01 | 2339402 | 4901 | G2 | Natus Vincere | 5 | Nuke | t | ct | 4350.0 | 1100.0 | 22100.0 | 9350.0 | 25750.0 | 10400.0 | 24600.0 | 8150.0 | 26700.0 | 23400.0 | 4300.0 | 25900.0 | 11950.0 | 24850.0 | 21900.0 | 4150.0 | 10650.0 | 27300.0 | 27000.0 | 30950.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 4250.0 | 20250.0 | 24600.0 | 29300.0 | 30650.0 | 31450.0 | 32050.0 | 31450.0 | 32050.0 | 30950.0 | 29300.0 | 30200.0 | 31550.0 | 32350.0 | 33050.0 | 4250.0 | 20300.0 | 8250.0 | 1300.0 | 22200.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 2.0 | 2.0 | 2.0 | 2.0 | 2.0 | 2.0 | 2.0 | 2.0 | 1.0 | 2.0 | 2.0 | 2.0 | 2.0 | 2.0 | 2.0 | 2.0 | 1.0 | 1.0 | 1.0 | 2.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1 | 2020-03-01 | 2339402 | 4901 | G2 | Natus Vincere | 5 | Dust2 | ct | t | 3900.0 | 7400.0 | 23250.0 | 28500.0 | 31900.0 | 31700.0 | 18950.0 | 30200.0 | 28650.0 | 30350.0 | 30150.0 | 11100.0 | 23700.0 | 8550.0 | 26350.0 | 4050.0 | 9400.0 | 21900.0 | 12700.0 | 11300.0 | 3100.0 | 26250.0 | 21300.0 | 23950.0 | 27450.0 | 27550.0 | 28050.0 | 26250.0 | 26250.0 | NaN | 3500.0 | 18550.0 | 7300.0 | 1500.0 | 21800.0 | 12000.0 | 21050.0 | 24450.0 | 6850.0 | 26850.0 | 23100.0 | 25650.0 | 26800.0 | 26750.0 | 28250.0 | 4000.0 | 18850.0 | 15850.0 | 23000.0 | 26850.0 | 29100.0 | 26300.0 | 26850.0 | 19050.0 | 3500.0 | 26450.0 | 27450.0 | 27500.0 | 29050.0 | NaN | 2.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 2.0 | 1.0 | 1.0 | 2.0 | 2.0 | 2.0 | 2.0 | 2.0 | 2.0 | 2.0 | 1.0 | 2.0 | 2.0 | 2.0 | 2.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 2.0 | 2.0 | 2.0 | NaN |
2 | 2020-03-01 | 2339402 | 4901 | G2 | Natus Vincere | 5 | Mirage | t | ct | 4150.0 | 14300.0 | 2000.0 | 24800.0 | 9000.0 | 23150.0 | 21850.0 | 23700.0 | 10450.0 | 26250.0 | 8800.0 | 24950.0 | 12100.0 | 24350.0 | 18250.0 | 4300.0 | 19400.0 | 8900.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 4200.0 | 21200.0 | 24150.0 | 27050.0 | 31350.0 | 30650.0 | 31050.0 | 28150.0 | 29650.0 | 30950.0 | 31550.0 | 32950.0 | 32250.0 | 31650.0 | 33350.0 | 4350.0 | 14300.0 | 22850.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 2.0 | 2.0 | 2.0 | 2.0 | 2.0 | 2.0 | 1.0 | 2.0 | 2.0 | 2.0 | 2.0 | 2.0 | 2.0 | 2.0 | 2.0 | 1.0 | 2.0 | 2.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
3 | 2020-02-29 | 2339401 | 4901 | Natus Vincere | Astralis | 3 | Dust2 | t | ct | 4150.0 | 18050.0 | 21000.0 | 25850.0 | 25000.0 | 25000.0 | 27250.0 | 26150.0 | 26300.0 | 27850.0 | 26750.0 | 27450.0 | 27850.0 | 18300.0 | 27850.0 | 4000.0 | 21100.0 | 9100.0 | 3100.0 | 22100.0 | 23350.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 4250.0 | 9300.0 | 2100.0 | 19300.0 | 27250.0 | 9850.0 | 24800.0 | 12200.0 | 27550.0 | 26100.0 | 7450.0 | 27650.0 | 24500.0 | 19100.0 | 18050.0 | 4150.0 | 15100.0 | 18450.0 | 23150.0 | 28150.0 | 27850.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 1.0 | 1.0 | 1.0 | 2.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 2.0 | 2.0 | 2.0 | 2.0 | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
4 | 2020-02-29 | 2339401 | 4901 | Natus Vincere | Astralis | 3 | Nuke | ct | t | 4200.0 | 10000.0 | 22000.0 | 24500.0 | 27550.0 | 29350.0 | 31950.0 | 31850.0 | 31750.0 | 32850.0 | 32150.0 | 31750.0 | 31850.0 | 33050.0 | 33150.0 | 4250.0 | 3000.0 | 21150.0 | 11750.0 | 28050.0 | 25900.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 4200.0 | 17950.0 | 9050.0 | 1000.0 | 22850.0 | 7500.0 | 24400.0 | 24700.0 | 9700.0 | 27150.0 | 21850.0 | 21900.0 | 8150.0 | 25200.0 | 20450.0 | 4300.0 | 19300.0 | 27400.0 | 31700.0 | 29650.0 | 12150.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 2.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 2.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 2.0 | 2.0 | 2.0 | 1.0 | 1.0 | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
players_df.head()
date | player_name | team | opponent | country | player_id | match_id | event_id | event_name | best_of | map_1 | map_2 | map_3 | kills | assists | deaths | hs | flash_assists | kast | kddiff | adr | fkdiff | rating | m1_kills | m1_assists | m1_deaths | m1_hs | m1_flash_assists | m1_kast | m1_kddiff | m1_adr | m1_fkdiff | m1_rating | m2_kills | m2_assists | m2_deaths | m2_hs | m2_flash_assists | m2_kast | m2_kddiff | m2_adr | m2_fkdiff | m2_rating | m3_kills | m3_assists | m3_deaths | m3_hs | m3_flash_assists | m3_kast | m3_kddiff | ... | m3_fkdiff | m3_rating | kills_ct | deaths_ct | kddiff_ct | adr_ct | kast_ct | rating_ct | kills_t | deaths_t | kddiff_t | adr_t | kast_t | rating_t | m1_kills_ct | m1_deaths_ct | m1_kddiff_ct | m1_adr_ct | m1_kast_ct | m1_rating_ct | m1_kills_t | m1_deaths_t | m1_kddiff_t | m1_adr_t | m1_kast_t | m1_rating_t | m2_kills_ct | m2_deaths_ct | m2_kddiff_ct | m2_adr_ct | m2_kast_ct | m2_rating_ct | m2_kills_t | m2_deaths_t | m2_kddiff_t | m2_adr_t | m2_kast_t | m2_rating_t | m3_kills_ct | m3_deaths_ct | m3_kddiff_ct | m3_adr_ct | m3_kast_ct | m3_rating_ct | m3_kills_t | m3_deaths_t | m3_kddiff_t | m3_adr_t | m3_kast_t | m3_rating_t | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2020-02-26 | Brehze | Evil Geniuses | Liquid | United States | 9136 | 2339385 | 4901 | IEM Katowice 2020 | 3 | Overpass | Nuke | Inferno | 57 | 14 | 61 | 29 | 0.0 | 71.1 | -4 | 79.9 | 0 | 1.04 | 11 | 3 | 18 | 5 | 0.0 | 65.2 | -7 | 60.8 | -1 | 0.70 | 30.0 | 7.0 | 24.0 | 16.0 | 0.0 | 73.5 | 6.0 | 99.2 | 6.0 | 1.38 | 16.0 | 4.0 | 19.0 | 8.0 | 0.0 | 73.1 | -3.0 | ... | -5.0 | 0.91 | 34.0 | 30.0 | 4.0 | 81.6 | 79.2 | 1.10 | 23.0 | 31.0 | -8.0 | 77.5 | 60.0 | 0.97 | 8.0 | 10.0 | -2.0 | 76.3 | 73.3 | 0.90 | 3.0 | 8.0 | -5.0 | 31.9 | 50.0 | 0.34 | 17.0 | 10.0 | 7.0 | 93.7 | 83.3 | 1.41 | 13.0 | 14.0 | -1.0 | 105.3 | 62.5 | 1.35 | 9.0 | 10.0 | -1.0 | 72.5 | 80.0 | 0.93 | 7.0 | 9.0 | -2.0 | 70.4 | 63.6 | 0.89 |
1 | 2020-02-26 | CeRq | Evil Geniuses | Liquid | Bulgaria | 11219 | 2339385 | 4901 | IEM Katowice 2020 | 3 | Overpass | Nuke | Inferno | 54 | 10 | 54 | 18 | 4.0 | 65.1 | 0 | 71.7 | 2 | 0.98 | 11 | 2 | 17 | 4 | 2.0 | 60.9 | -6 | 68.9 | -1 | 0.75 | 26.0 | 6.0 | 19.0 | 8.0 | 1.0 | 76.5 | 7.0 | 80.1 | 3.0 | 1.24 | 17.0 | 2.0 | 18.0 | 6.0 | 1.0 | 53.8 | -1.0 | ... | 0.0 | 0.87 | 37.0 | 25.0 | 12.0 | 77.4 | 72.9 | 1.16 | 17.0 | 29.0 | -12.0 | 63.9 | 54.3 | 0.73 | 9.0 | 9.0 | 0.0 | 72.3 | 73.3 | 0.88 | 2.0 | 8.0 | -6.0 | 62.4 | 37.5 | 0.50 | 15.0 | 6.0 | 9.0 | 79.8 | 88.9 | 1.45 | 11.0 | 13.0 | -2.0 | 80.5 | 62.5 | 1.00 | 13.0 | 10.0 | 3.0 | 79.5 | 53.3 | 1.12 | 4.0 | 8.0 | -4.0 | 40.7 | 54.5 | 0.53 |
2 | 2020-02-26 | EliGE | Liquid | Evil Geniuses | United States | 8738 | 2339385 | 4901 | IEM Katowice 2020 | 3 | Overpass | Nuke | Inferno | 55 | 10 | 51 | 28 | 1.0 | 67.5 | 4 | 77.9 | 1 | 1.08 | 15 | 3 | 12 | 9 | 0.0 | 69.6 | 3 | 77.0 | 3 | 1.32 | 24.0 | 3.0 | 24.0 | 14.0 | 0.0 | 64.7 | 0.0 | 72.9 | -1.0 | 0.97 | 16.0 | 4.0 | 15.0 | 5.0 | 1.0 | 69.2 | 1.0 | ... | -1.0 | 1.04 | 31.0 | 17.0 | 14.0 | 96.6 | 71.4 | 1.39 | 24.0 | 34.0 | -10.0 | 64.2 | 64.6 | 0.86 | 11.0 | 2.0 | 9.0 | 135.2 | 75.0 | 2.17 | 4.0 | 10.0 | -6.0 | 45.9 | 66.7 | 0.87 | 13.0 | 9.0 | 4.0 | 87.6 | 75.0 | 1.26 | 11.0 | 15.0 | -4.0 | 59.7 | 55.6 | 0.71 | 7.0 | 6.0 | 1.0 | 81.5 | 63.6 | 1.03 | 9.0 | 9.0 | 0.0 | 87.9 | 73.3 | 1.05 |
3 | 2020-02-26 | Ethan | Evil Geniuses | Liquid | United States | 10671 | 2339385 | 4901 | IEM Katowice 2020 | 3 | Overpass | Nuke | Inferno | 43 | 5 | 54 | 18 | 2.0 | 65.1 | -11 | 58.7 | -4 | 0.83 | 11 | 1 | 15 | 6 | 1.0 | 65.2 | -4 | 60.7 | -2 | 0.73 | 22.0 | 3.0 | 21.0 | 8.0 | 1.0 | 70.6 | 1.0 | 67.9 | -2.0 | 1.00 | 10.0 | 1.0 | 18.0 | 4.0 | 0.0 | 57.7 | -8.0 | ... | 0.0 | 0.69 | 33.0 | 23.0 | 10.0 | 74.0 | 75.0 | 1.11 | 10.0 | 31.0 | -21.0 | 37.8 | 51.4 | 0.43 | 9.0 | 8.0 | 1.0 | 68.3 | 73.3 | 0.92 | 2.0 | 7.0 | -5.0 | 46.5 | 50.0 | 0.38 | 15.0 | 6.0 | 9.0 | 84.3 | 83.3 | 1.40 | 7.0 | 15.0 | -8.0 | 49.3 | 56.2 | 0.55 | 9.0 | 9.0 | 0.0 | 67.2 | 66.7 | 0.97 | 1.0 | 9.0 | -8.0 | 14.8 | 45.5 | 0.31 |
4 | 2020-02-26 | NAF | Liquid | Evil Geniuses | Canada | 8520 | 2339385 | 4901 | IEM Katowice 2020 | 3 | Overpass | Nuke | Inferno | 52 | 22 | 46 | 23 | 9.0 | 77.1 | 6 | 75.9 | -1 | 1.08 | 10 | 5 | 12 | 3 | 3.0 | 65.2 | -2 | 51.5 | 0 | 0.83 | 29.0 | 6.0 | 21.0 | 16.0 | 0.0 | 82.4 | 8.0 | 101.9 | 0.0 | 1.35 | 13.0 | 11.0 | 13.0 | 4.0 | 6.0 | 80.8 | 0.0 | ... | -1.0 | 0.98 | 28.0 | 17.0 | 11.0 | 96.3 | 85.7 | 1.36 | 24.0 | 29.0 | -5.0 | 61.0 | 70.8 | 0.87 | 4.0 | 3.0 | 1.0 | 64.8 | 62.5 | 0.98 | 6.0 | 9.0 | -3.0 | 44.4 | 66.7 | 0.75 | 19.0 | 8.0 | 11.0 | 128.1 | 100.0 | 1.88 | 10.0 | 13.0 | -3.0 | 78.7 | 66.7 | 0.89 | 5.0 | 6.0 | -1.0 | 72.9 | 81.8 | 0.96 | 8.0 | 7.0 | 1.0 | 56.3 | 80.0 | 0.99 |
5 rows × 101 columns
Os dados coletados contêm dados de todas as partidas profissionais de CS:GO, incluindo partidas de times relativamente desconhecidos. Por esse motivo, limitaremos os conjuntos de dados às partidas disputadas entre os 30 melhores times do ranking HLTV.
min_rank = 30
results_df = results_df[(results_df.rank_1<min_rank)&(results_df.rank_2<min_rank)]
picks_df = picks_df [picks_df .match_id.isin(results_df.match_id.unique())]
economy_df = economy_df[economy_df.match_id.isin(results_df.match_id.unique())]
players_df = players_df[players_df.match_id.isin(results_df.match_id.unique())]
winner_1 = results_df[results_df.result_1>=results_df.result_2].result_1.values
loser_1 = results_df[results_df.result_1>=results_df.result_2].result_2.values
winner_2 = results_df[results_df.result_1<results_df.result_2].result_2.values
loser_2 = results_df[results_df.result_1<results_df.result_2].result_1.values
winner = np.concatenate((winner_1,winner_2))
loser = np.concatenate((loser_1,loser_2))
scores_df = pd.DataFrame(np.vstack((winner,loser)).T,columns=['winner','loser'])
gb = scores_df.groupby(by=['winner','loser'])['winner'].count()/scores_df.shape[0]
overtime_percentage = str(round(gb[gb.index.get_level_values(0)!=16].sum()*100,1))+'%'
gb = round(gb[gb>10**-3]*100,1)
index_plot = np.array(gb.index.get_level_values(0).astype('str'))+'-'+np.array(
gb.index.get_level_values(1).astype('str'))
fig = go.Figure()
fig.add_trace(go.Scatter(x=index_plot,y=gb.values, name='results'))
fig.update_layout(xaxis_type='category',title='Scores distribution',xaxis_title='Score',yaxis_title='Percentage of matches (%)')
overtime_percentage
'9.7%'
Podemos observar que no tempo regulamentar (desconsiderando a prorrogação), o placar mais comum é 16-14 (obtido em 10,7% das partidas) e o mais raro é 16-0 (obtido em apenas 0,2% das partidas), com intermediários pontuações caindo em algum lugar no meio.
9,7% das partidas vão para a prorrogação.
Os resultados podem diferir se considerarmos partidas disputadas por times que não são de primeira linha.
Há muito tempo existe uma disputa no CS:GO para determinar os mapas mais favoráveis aos CTs, e sempre há discussão se ter um mapa muito desequilibrado é um resultado desejável. Aqui determinamos essa característica calculando as pontuações médias obtidas em cada lado do mapa e depois comparando ambos os lados.
ct_1 = results_df[['date','_map','ct_1']].rename(columns={'ct_1':'ct'})
ct_2 = results_df[['date','_map','ct_2']].rename(columns={'ct_2':'ct'})
ct = pd.concat((ct_1,ct_2))
t_1 = results_df[['date','_map','t_1']].rename(columns={'t_1':'t'})
t_2 = results_df[['date','_map','t_2']].rename(columns={'t_2':'t'})
t = pd.concat((t_1,t_2))
t = t.sort_values('date')
ct = ct.sort_values('date')
maps = ['Cache','Cobblestone','Dust2','Inferno','Mirage','Nuke','Overpass','Train','Vertigo']
series_t, series_ct, how_ct = {},{},{}
for i, key in enumerate(maps):
t_map = t[t._map == maps[i]]
ct_map = ct[ct._map == maps[i]]
y_t = t_map.t.rolling(min_periods = 20, window= 200, center=True).sum().values
y_ct = ct_map.ct.rolling(min_periods = 20, window= 200, center=True).sum().values
series_t[key] = pd.Series(data=y_t,index=t_map.date)
series_ct[key] = pd.Series(data=y_ct,index=ct_map.date)
how_ct[key] = series_ct[key]/(series_ct[key]+series_t[key])//0.001/10
def add_trace(_map):
fig.add_trace(go.Scatter(x=how_ct[_map].index, y=how_ct[_map].values, name=_map))
fig = go.Figure()
for _map in maps:
add_trace(_map)
fig.add_trace(go.Scatter(x=['2015-11-01', '2020-03-12'], y=[50,50],
mode='lines',line=dict(color='grey'),showlegend=False))
fig.update_layout(title='Distribution of rounds between CT and T sides',
yaxis_title='Percentage of round won on the CT-side (%)')
fig.show()
Existem longos períodos sem dados para um mapa no gráfico. Isso ocorre porque os mapas são adicionados e removidos constantemente da lista de mapas disponíveis.
Nuke e Train oscilam como sendo os mapas mais favoráveis aos CTs, tendo cerca de 57% das rodadas vencidas pelos CTs, enquanto Dust2 e Cache são historicamente os mapas mais favoráveis aos Terroristas (T).
É interessante notar que Inferno era conhecido por ser um mapa muito favorável aos CTs antes de 2016, o que foi uma das razões para atualizá-lo. Desde a sua atualização, Inferno tem sido o mapa mais equilibrado nesse aspecto.
Mirage, Train, Inferno e Overpass são os mapas dos quais temos mais dados disponíveis. Eles também são os mapas presentes no mapa de jogo por mais tempo;
Cache, Cobblestone e Dust2 foram jogados menos vezes, mas também estiveram fora do mapa de jogo por longos períodos:
Nuke é historicamente o mapa menos jogado, mesmo estando presente no mapa de jogo por muito tempo. A única explicação para isso vem da falta de familiaridade das equipes com o mapa;
Vertigo tem dados limitados disponíveis, pois foi o mapa mais recentemente adicionado ao mapa de jogo.
print('Total number of matches played on the map:')
results_df.groupby('_map').date.count()
Total number of matches played on the map:
_map
Cache 900
Cobblestone 898
Default 2
Dust2 892
Inferno 1325
Mirage 1617
Nuke 750
Overpass 1150
Train 1384
Vertigo 99
Name: date, dtype: int64
No CS:GO, os torneios mais respeitados são os Majors. Esses torneios são normalmente disputados duas vezes por ano e têm um prêmio de $1.000.000. Mais informações sobre o assunto podem ser vistas aqui: https://liquipedia.net/counterstrike/Majors
Para a próxima etapa, vamos discretizar a coluna 'data' em um dataframe em uma coluna 'time_period'. Essa nova coluna se referirá ao torneio Major mais recentemente disputado.
Como exemplo, seguindo essa técnica de binning, atualmente estamos no período de Berlim 2019, pois esse foi o torneio mais recentemente disputado.
majors = [{'tournament':'01. Cluj-Napoca 2015','start_date':'2015-10-28'},
{'tournament':'02. Columbus 2016','start_date':'2016-03-29'},
{'tournament':'03. Cologne 2016','start_date':'2016-07-05'},
{'tournament':'04. Atlanta 2017','start_date':'2017-01-22'},
{'tournament':'05. Krakow 2017','start_date':'2017-07-16'},
{'tournament':'06. Boston 2018','start_date':'2018-01-26'},
{'tournament':'07. London 2018','start_date':'2018-09-20'},
{'tournament':'08. Katowice 2019','start_date':'2019-02-28'},
{'tournament':'09. Berlin 2019','start_date':'2019-09-05'}]
def create_col_time_period(df):
df['time_period'] = ''
for major_start in majors:
df.loc[(df['date']>=major_start['start_date']),'time_period'] = major_start['tournament']
return df
results_df = create_col_time_period(results_df)
economy_df = create_col_time_period(economy_df)
picks_df = create_col_time_period(picks_df)
players_df = players_df.merge(results_df[['match_id','time_period']],'left',on='match_id')
results_df_team_1 = results_df[['time_period','team_1','_map','ct_1','t_2','ct_2','t_1']
].rename(columns={'team_1':'team'})
results_df_team_2 = results_df[['time_period','team_2','_map','ct_1','t_2','ct_2','t_1']
].rename(columns={'team_2':'team'})
results_df_teams = pd.concat((results_df_team_1,results_df_team_2))[['time_period','team','_map']]
gb = results_df_teams.groupby(['time_period','_map']).team.count()
gb_text = round(gb*100/gb.groupby('time_period').sum(),1).reset_index().rename(columns={'team':'percentage'})
gb_text.percentage = gb_text.percentage.astype(str)+'%'
gb = gb.reset_index()
fig = go.Figure()
for _map in maps:
fig.add_bar(name=_map,x=gb[gb._map==_map].time_period,y=gb[gb._map==_map].team,
text=gb_text[gb_text._map==_map].percentage,textposition='inside')
fig.update_layout(barmode='stack',legend=dict(traceorder='normal'),yaxis_title='Number of maps played',font=dict(size=10))
fig.show()
Como apontado anteriormente, Nuke é historicamente o mapa menos popular do mapa de jogo. Isso tem mudado recentemente, já que equipes que costumavam eliminar o mapa agora estão banindo mapas como Vertigo.
Vertigo, como o mapa mais novo e não convencional, também é o mapa menos popular, provavelmente devido às muitas mudanças que teve em seu curto período competitivo.
O período entre Columbus e Cologne 2016 tem a menor quantidade de mapas jogados e também é o mais curto (com menos de 4 meses), enquanto o período entre Boston e Londres 2018 tem a maior quantidade de mapas jogados e também é o mais longo (com mais de 7 meses).