{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\\[ Stefano Pigozzi | Tema Data Analytics | Big Data Analytics | A.A. 2022/2023 | Unimore \\]" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2023-07-02T06:47:40.635561319Z", "start_time": "2023-07-02T06:47:39.216048338Z" } }, "outputs": [], "source": [ "%load_ext autoreload\n", "%autoreload 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Ricerca di correlazioni nell'attività online relativa a videogiochi pubblicati sulla piattaforma Steam" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> ### Data processing e exploratory data analytics su dataset provenienti da più sorgenti\n", ">\n", "> L’attività da svolgere consiste nel:\n", ">\n", "> 1. Scegliere due o più dataset provenienti da due o più sorgenti.\n", "> * Il dataset finale deve essere costituito almeno da due file.\n", "> 2. Usando [pandas](https://pandas.pydata.org/) implementare le operazioni di data processing necessarie (principalmente join e selezioni) per mettere in collegamento i dataset e per preparare i dati al passo successivo\n", "> 3. Usando pacchetti Python quali [pandas](https://pandas.pydata.org/), [scipy](https://scipy.org/), [matplotlib](https://matplotlib.org/) e [seaborn](https://seaborn.pydata.org/) implementare attività di data cleaning, exploratory data analysis estraendo dati statistici e di visualizzazione dei risultati attraverso il quale sia possibile \"raccontare qualcosa sui dati\" (storytelling), eventualmente partendo da dei quesiti di ricerca.\n", "> L'uso dei pacchetti non deve necessariamente essere limitato alle istruzioni viste a lezione. Le documentazioni dei pacchetti stessi e i volumi messi a disposizione su Dolly fornisco spunti d’uso interessanti!\n", "> 4. Produrre un notebook [Jupyter](https://jupyter.org/) che contenga:\n", "> * una introduzione all’argomento scelto, alle sorgenti dati e agli obiettivi del progetto specificando eventualmente i quesiti di ricerca\n", "> * una sezione per ogni fase del progetto di data analytics" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Sinossi" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In questa relazione si ricercano correlazioni tra vari parametri relativi all'attività online riguardante vari videogiochi per PC pubblicati sulla piattaforma di distribuzione [Steam](https://store.steampowered.com/), recuperando dati da varie fonti, quali la web API di [Steam](https://store.steampowered.com/) stesso, il progetto [SteamDB](https://steamdb.info/), il catalogo prezzi [IsThereAnyDeal](https://isthereanydeal.com/), e [Google Trends](https://trends.google.com/trends/), costruendo infine un funzione con discreta correlazione con il numero di giocatori attivi in un determinato giorno." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Introduzione" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Steam](https://store.steampowered.com/) è una piattaforma di vendita e distribuzione videogiochi per PC creata da [Valve Corporation](https://www.valvesoftware.com/en/)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Valve Corporation](https://www.valvesoftware.com/en/) pubblica quotidianamente [dati sul numero massimo di giocatori concorrenti](https://store.steampowered.com/charts/) di ciascun videogioco; questi dati vengono raccolti dal progetto indipendente [SteamDB](https://steamdb.info/), che li utilizza per mostrare la popolarità storica di ciascun prodotto." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Periodicamente, i videogiochi disponibili su [Steam](https://store.steampowered.com/) vengono scontati temporaneamente per incentivare gli utenti della piattaforma ad acquistarli; ciò in genere avviene tra le due e le cinque volte all'anno, principalmente nel periodo natalizio e attorno al solstizio di estate.\n", "\n", "Il progetto [SteamDB](https://steamdb.info/) monitora quotidianamente i prezzi di ciascun prodotto, aggregandoli per creare uno storico complessivo dei prezzi." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "I videogiochi presenti su [Steam](https://store.steampowered.com/) possono essere anche acquistati attraverso siti di terze parti, che possono offrire prezzi o offerte diversi da quelli della piattaforma, pur sempre condividendone i servizi, come ad esempio [Humble Bundle](https://www.humblebundle.com/); il catalogo prezzi [IsThereAnyDeal](https://isthereanydeal.com/) si occupa di controllare periodicamente i prezzi su ciascun rivenditore e di aggregarli in un sito unico, creando poi uno storico globale dei prezzi migliori." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Gli sviluppatori dei videogiochi su [Steam](https://store.steampowered.com/) possono pubblicare periodicamente sulla piattaforma degli annunci relativi al proprio videogioco, tipicamente per informare i clienti della disponibilità di una nuova release." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Gli annunci pubblicati da ciascun prodotto sono recuperabili attraverso chiamate ad una [web API](https://developer.valvesoftware.com/wiki/Steam_Web_API#GetNewsForApp_.28v0002.29) pubblica." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Obiettivo dell'indagine" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La popolarità di un videogioco è una metrica sociale, alimentata da tanti diversi fattori, che possono variare anche significativamente in base al genere in questione." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si ipotizza che uno di questi fattori sia la presenza di sconti, in quanto si è empiricamente notato che il numero di giocatori sembra aumentare in presenza di essi." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si ipotizza inoltre che il rilascio di nuovi contenuti porti a un picco improvviso seguito da una lenta diminuzione nel numero di giocatori concorrenti, circa corrispondente al tempo necessario per vedere le novità." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In questa indagine, si vuole provare a modellare una funzione che, utilizzando solo parametri esterni, ottenga una discreta correlazione con il numero di giocatori concorrenti di ciascun videogioco (senza ricorrere a tecniche di machine learning)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Oggetto dell'indagine" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Recuperare grandi quantità di dati relative a un vasto numero di prodotti diversi è difficoltoso, in quanto tutte le fonti che si desidera utilizzare implementano misure per prevenire lo scraping automatizzato." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Inoltre, la moltitudine di generi di videogiochi esistenti e di stili di comunicazione adottati dagli sviluppatori può introdurre notevole rumore e rendere questo studio impossibile. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si decide pertanto di concentrarsi esclusivamente sui prodotti con le seguenti caratteristiche:\n", "\n", "- ne è stata rilasciata la versione 1.0\n", "- non hanno fattori fortemente sociali come origine della loro popolarità\n", " - la loro componente principale non è il multigiocatore competitivo\n", "- vengono scontati regolarmente\n", "- non abusano della funzionalità di annunci per pubblicare informazioni non riguardanti il prodotto\n", "- hanno venduto un numero significativo di copie\n", " - hanno almeno 10000 recensioni pubblicate dai clienti" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si recupera quindi manualmente un piccolo sottoinsieme di dataset relativi a diversi prodotti con le caratteristiche indicate nella sezione precedente, descrivendo però accuratamente il metodo utilizzato per recuperare i dati in modo da poter estendere riproducibilmente la ricerca a qualsiasi altro prodotto." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "I prodotti selezionati sono:\n", "\n", "- [Deep Rock Galactic](https://steamdb.info/app/548430/)\n", "- [OMORI](https://steamdb.info/app/1150690/)\n", "- [Potion Craft: Alchemist Simulator](https://steamdb.info/app/1210320/)\n", "- [Untitled Goose Game](https://steamdb.info/app/837470/)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In più, al fine di mostrare quanta differenza può esserci tra un prodotto e l'altro, si recuperano anche dati relativi a questo videogioco, che non presenta le caratteristiche sopraelencate:\n", "\n", "- [Factorio](https://steamdb.info/app/427520/)\n", " - non è mai stato scontato\n", " - ha pubblicato per anni nella sezione annunci un diario settimanale dello sviluppo\n", " - viene aggiornato regolarmente, ma solo per correzione di bug, e non per l'aggiunta di nuovi contenuti" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Struttura del progetto" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il progetto è diviso in tre parti:\n", "\n", "- la directory `data` con i dati grezzi recuperati dalla rete, con a sua volta tante sottodirectory con i dati specifici di ciascun prodotto studiato;\n", "- il package Python `unimore_bda_3`, contenente primitive specifiche all'elaborazione dei dati;\n", "- questo notebook Jupyter, contenente celle per la rappresentazione dei dati elaborati." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il package contiene un modulo particolare, `unimore_bda_3.prelude`, che importa tutte le dipendenze necessarie allo svolgimento dell'analisi e le ri-esporta con degli alias semplici e intuitivi." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il package è compatibile con PEP518; per installarlo, è necessario eseguire i seguenti comandi dalla directory del progetto:\n", "\n", "```bash\n", "python3 -v venv .venv\n", "source venv/bin/activate # Assumendo l'utilizzo di Bash\n", "pip install .\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si importa il modulo all'interno del notebook, in modo da avere tutti gli alias disponibili:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "ExecuteTime": { "end_time": "2023-07-02T06:47:40.693759958Z", "start_time": "2023-07-02T06:47:39.216569683Z" } }, "outputs": [], "source": [ "from unimore_bda_3.prelude import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Recupero manuale dei dati" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In questa sezione si recuperano manuale dati machine-readable da diverse fonti indipendenti fra loro, evitando di incappare in protezioni automatizzate insuperabili come CAPTCHA." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### [Google Trends](https://trends.google.com/trends/)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si cercano su Google Trends i prodotti oggetto di questa ricerca, facendo attenzione a selezionare l'*argomento \"Videogioco\"* e non il *termine di ricerca* con lo stesso nome per minimizzare i falsi positivi." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![Visualizzazione di come effettuare una ricerca su Google Trends attraverso interfaccia grafica.](media/google-trends-query.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si configura poi la ricerca perchè sia relativa a *Tutto il mondo* e nell'arco di tempo *2004 - Presente*, in modo da avere dati generali relative alle tendenze globali, e poi si utilizza il pulsante *Download* per scaricare il file CSV relativo all'*Interesse nel tempo*." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![Visualizzazione di come configurare i parametri di una ricerca su Google Trends attraverso interfaccia grafica, e di come scaricarne i risultati.](media/google-trends-parameters.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "I file CSV così recuperati sono inseriti al percorso `data/{nome}/gtrends-worldwide.csv`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### [SteamDB](https://steamdb.info/)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si cercano su SteamDB i prodotti oggetto della ricerca." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![Visualizzazione di come effettuare una ricerca su SteamDB attraverso interfaccia grafica.](media/steamdb-search.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dalla pagina di ciascun prodotto si recupera l'App ID, un codice univoco utilizzato da Steam per identificare il software, e lo si salva all'interno del file `data/{nome}/steam_appid.txt`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![Visualizzazione di come recuperare l'App ID di un prodotto dalla relativa pagina SteamDB.](media/steamdb-appid.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si accede poi alla scheda *Price History*." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![Visualizzazione di come accedere alla scheda Price History.](media/steamdb-tab-price-history.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In fondo ad essa, nella omonima sezione, è presente un grafico dello storico prezzi, con a destra un bottone per il download del dataset." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![Visualizzazione di come scaricare il dataset dello storico prezzi.](media/steamdb-chart-price-history.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il file recuperato viene salvato con il nome `data/{nome}/steamdb-price.csv`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si accede poi alla scheda *Charts*." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![Visualizzazione di come accedere alla scheda Charts.](media/steamdb-tab-charts.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Poco sotto la selezione, si trova la sezione *Lifetime player count history*, contenente un grafico dello storico del numero di giocatori concorrenti dalla comparsa del prodotto su Steam, con a destra un bottone per il download del dataset." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![Visualizzazione di come scaricare il dataset dello storico prezzi.](media/steamdb-chart-player-history.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il file recuperato viene salvato con il nome `data/{nome}/steamdb-players.csv`.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### [IsThereAnyDeal](https://isthereanydeal.com/)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si cercano sul sito `https://new.isthereanydeal.com` i cinque prodotti relativi a questa ricerca." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![Visualizzazione di come cercare prodotti su IsThereAnyDeal.](media/itad-search.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si accede alla scheda *History*, e si utilizza il tool *Ispeziona Elemento* del browser Firefox per accedere al sorgente HTML della pagina dopo che essa ha eseguito il codice JavaScript necessario per la visualizzazione dei grafici." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![Visualizzazione di come ispezionare il grafico nei Firefox Developer Tools.](media/itad-inspect-element.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dal grafico, si risale la gerarchia degli elementi fino ad arrivare a un `