Nochmal Serien Plots, XKCD Style

Immer noch ziemlich nutzlos aber diesmal mit XKCD-Eyecandy. Bokeh ist ja ganz schön, braucht aber eine ziemlich große JS-Komponente die immer geladen werden muss. Mit matplotlib kann man statische Grafen zeichnen und mit %matplotlib notebook vorher einen Auschnitt wählen.

Ich wollte mal schauen wie sich die Ratingverläufe der Staffeln einer Serie entfalten. Eventuell kann man ja ein daramaturgischen Verlauf erkennen. Ich als jemand der selber keine Ratings abgibt. Alles befindet sich doch ziemlich auf einem Level.

In [1]:
import pandas as pd
import matplotlib
import numpy as np
from trakt.tv import TVShow

Nach dem import der Libs führen wir folgendes Jupyter-Magic aus um die erzeugten Plots im Notebook noch leicht anpassen zu könne.

In [2]:
%matplotlib notebook

Wir aktivieren die XKCD-Style-Plots:

In [3]:
matplotlib.pyplot.xkcd()
Out[3]:
<matplotlib.rc_context at 0xaf0ef58c>

Nun kommt die Funktion die alle Daten einsammelt und ausgibt:

In [4]:
def season_ratings(name):
    tv_show = TVShow(name)
    
    data = {}
    for season in tv_show.seasons:
    
        if season.season == 0:
            continue
    
        ratings = []
        for episode in season.episodes:
            ratings.append(episode.rating)
    
        data[season.season] = pd.Series(ratings)

    df = pd.DataFrame(data)
    df.plot(colormap=matplotlib.cm.Accent)

Beispiele

In [5]:
season_ratings('The IT-Crowd')
In [6]:
season_ratings('Roswell')
In [7]:
season_ratings('Veronica Mars')
In [8]:
season_ratings('Breaking Bad')
In [9]:
season_ratings('Community')

Ratingverläufe unterschiedlicher Serien

Nun lassen wir mal ein paar Serien gegeneinander antreten. Dabei betrachten wir immer alle Episoden aller Staffeln.

In [12]:
def series_ratings(series):
    data = {}
    
    for serie in series:
        
        show = TVShow(serie)
        
        ratings = []
        for season in show.seasons:
            
            if season.season == 0:
                continue
            
            for episode in season.episodes:
                ratings.append(episode.rating)
        
        data[serie] = pd.Series(ratings)
        
    df = pd.DataFrame(data)
    df.plot(colormap=matplotlib.cm.Accent)

Beispiel

In [13]:
series_ratings(['Gotham', 'Flash', 'Arrow', 'Supergirl'])

Mir ist gerade nichts Besseres eingefallen. Es müssen ja in irgendeinen Sinn vergleichbare Serien sein. Da habe ich mir mal die vier aktuellen DC-Serien angeschaut. Da Arrow schon einige Episoden mehr hat, habe ich den Plot angepasst und hinten abgeschnitten. Glaubt man den Ratings, hätte ich Supergirl doch mehr Chancen als zwei Folgen geben sollen. War in den ersten Folgen einfach zu glatt gebügelt.

Fernsehserien, Trakt, Jupyter und Bokeh

Datenvisualisierung hat mich schon immer fasziniert. Leider hatte ich nie einen wirklichen Grund dafür es einzusetzen. Und doch wollte ich es mal ausprobieren. Ich habe mich sehr von Jemus inspirieren lassen. Da passiert natürlich viel viel mehr und ausführlicher. Ich habe erstmal das gemacht was ich auch verstehe :). Und zwar die Episoden Ratings darzustellen.

Als erstes importiere ich ein paar Sachen. Erstmal choice um per Zufall Farben aus einer Palette auszuwählen. Dann pandas für die DataFrames. Um die Daten aus der Trakt-API zu bekommen benutze ich trakt.py. Wieso alles selber bauen wenn es dieses schöne Modul gibt? Dann benutze ich Bokeh um das ganze darzustellen.

In [1]:
from random import choice

import pandas as pd
from trakt.tv import TVShow
from bokeh.plotting import figure, ColumnDataSource, output_notebook, show
from bokeh.models import HoverTool
from bokeh.palettes import Spectral9

Wir starten die Bokeh Ausgabe in einem jupyter-Notebook.

In [2]:
output_notebook()
BokehJS successfully loaded.

Hier ist die Funktion die die Daten besorgt, verarbeitet und darstellt.

In [3]:
def ratings(show_name):
    
    # Es wird die Show definiert
    tv_show = TVShow(show_name)
    
    # Um die Staffeln ausseinander zu halten, soll jede Episode eine unterschiedliche 
    # Staffelfarbe haben. Bokeh hat ein paar Farbpaletten dabei. Ich benutze Spectral9.
    # Dazu brauchen wir noch eine liste um alle Episoden-Staffel-Farben zu speichern
    colormap = Spectral9
    colors = []
    
    # Wir brauchen eine Episoden Liste
    episodes = []
    
    # Damit die Episoden hintereinander auf der X-Achse dargestellt werden, brauchen sie
    # eine fortlaufende Nummer
    episode_number = 1
    
    # Dann arbeiten wir uns mal durch die Staffeln
    for season in tv_show.seasons:
        
        # Season 0 beinhaltet die Specials. Die werden ingnoriert
        if season.season == 0:
            continue
        
        # Eine Staffel-Farbe wird per Zufall ausgewaehlt. Wir schmeissen immer die letzte Farbe
        # aus einer Kopie der Farbenliste damit sie nicht nochmal gewaehlt wird
        if colors:
            new_colormap = colormap[:]
            new_colormap.remove(colors[-1])
            color = choice(new_colormap)
            
        else:
            color = choice(colormap)
        
        # Die Episoden 
        for episode in season.episodes:
            
            # Wenn es eine Ausstrahlungsdatum gibt, wird der Zeit-Teil weggeschnitten
            if episode.first_aired:
                aired = episode.first_aired.split('T')[0]
            else:
                aired = None
            
            # Nun werden die gesammelten Daten als Tupel der Episodenliste angehangen
            episodes.append((episode_number,
                             episode.season,
                             '{}.{}'.format(episode.season,
                                            episode.number), 
                              episode.title, 
                              aired, 
                              episode.rating))
            
            # Die Episoden-Staffel-Farbe wird der Farbenliste angehangen
            colors.append(color)
            
            # Die Episodennummer wird erhoeht
            episode_number += 1
                
    # Es wird ein DataFrame erstellt
    df = pd.DataFrame(
        episodes, 
        columns=['episode_number', 'season', 'episode', 'title', 'aired', 'rating'])

    # Es wird ein source-Objekt gebraucht damit die tooltips funktionieren.
    # Der DataFrame genuegt nicht um die Daten fuer die tooltips zu benutzen
    source = ColumnDataSource(data=df)
    
    # Wir erstellen in figure und belabeln die Achsen
    fig = figure(title=show_name)
    fig.xaxis.axis_label = 'Episodes'
    fig.yaxis.axis_label = 'Rating'
    
    # Hier bauen wir den Scatter-Plot. Wir uebergeben X und Y plus unser source-Objekt
    # und Style Geschichten. Unter anderem unsere Episoden-Farbenliste
    fig.scatter(df['episode_number'], df['rating'], 
                source=source, name='main', 
                fill_alpha=0.8, line_color='#000000', size=10, color=colors)
    
    # Ein HoverTool-Object in dem wir das Layout fuer die Tooltips festlegen
    hover = HoverTool(tooltips=[('Episode', '@episode'),
                                ('Title', '@title'),
                                ('Rating', '@rating'),
                                ('Aired', '@aired')])
    
    # Das Tool wird hinzugefuegt
    fig.add_tools(hover)
    
    # Und nun angezeigt
    show(fig)

Ich gebe eigentlich nicht viel auf die Ratings. Ich selber habe über Trakt noch nie etwas bewertet. Trotzdem handelt es sich um gute Daten um ein paar Sachen auszuprobieren.

Hier ein paar Ratings von Serien die mit entweder viel bedeuten oder die ich gerade schaue.

Roswell

In [4]:
ratings('Roswell')

Die erste Serie bei der ich von einem persönlichen Fandom sprechen kann. Noch bevor ich wusste das es das Wort gibt. Ich habe damals sogar alle Bücher gelesen. Kurz hatte ich nachgedacht sie wegzuschmeissen. Leicht peinlich berührt meiner Serienliebe von damals. Habe mich doch dagegen entschieden. Die erste Staffel war grossartig. Der perfekte Mix aus Highschool und SciFi/Mystery. Danach nahm es für mich drastisch ab. Die dritte Staffel habe ich noch nicht einmal schauen können. Zu gross war die Angst vor dem Zerstören meiner Liebe zur Serie.

Veronica Mars

In [5]:
ratings('Veronica Mars')

Vielleicht meine absolute Lieblingsserie. Veronica Mars habe ich vielleicht 4 oder 5 mal durchgeschaut. Und ich glaube dabei wird es nicht bleiben. Es so eine Serie die immer herhalten muss wenn es mir mal nicht so gut geht. Ein paar Folgen Veronica Mars sind immer eine gute Ablenkung. Alle drei Staffeln haben ungefähr die gleiche Bewertung. Dies deckt sich auch mit meiner Meinung. Drei gleich starke Staffeln. Wieso nur wurde die Serie abgesetzt? Das College-Szenario hätte noch soviel zu bieten gehabt.

Akte X

In [6]:
ratings('The X-Files')

Mit einem Knall wurde auf einmal eine zehnte Staffel angekündigt und gestern lief davon die dritte Folge. Auch wenn ich nur ein wenig mit Akte X vertraut bin, die drei Episoden haben mir bis jetzt sehr gefallen. Anscheinend alle Staffeln mit gleichen Höhen und Tiefen.

Downton Abbey

In [7]:
ratings('Downton Abbey')

Ich hätte nicht gedacht das mich diese Geschichte so packt und emotional macht. Doch Downton Abbey wurde für mich zu einer Herzensangelegenheit. Jeden Staffeln mit viel Tränen. Den Abfall der Ratings nach hinten decken sich nicht mit meiner Meinung. Ich fand alle 6 ziemlich stark.

Californication

In [8]:
ratings('Californication')

Eher so mal reingeschnuppert weil auf Netflix. Teilweise sehr unterhaltsam. Sonst kann ich nicht viel darüber sagen. Bin auch erst bei Staffel 4. Danach war ich wieder gesund und hatte keine Zeit mehr ;-).

Modern Family

In [9]:
ratings('Modern Family')