BAföG-Ausgaben im Vergleich zur wirtschaftlichen Entwicklung

Nach einer Diskussion über das BAföG und notwendige Reformen, bin ich bei bafoeg-rechner.de auf Zahlen zu den BAföG-Gesamtausgaben (ganz unten) gestoßen. Die prozentualen Steigerungen hier schienen mir so hoch, dass es lohnend schien, dies einmal zu visualisieren.

Da ich keine Zahlen zu den staatlichen Gesamteinnahmen gefunden habe, vergleiche ich die BAföG-Entwicklung mit der Wirtschaftsleistung gemessen durch das BIP. Die Staatseinnahmen gab es beim statistischen Bundesamt lediglich separiert in Einnahmengruppen, wobei Steuereinnahmen natürlich den größten, aber nicht einzigen Teil ausmachen.

Die Entwicklung des Bruttoinlandprodukts in Deutschland finden wir auch beim Statistischen Bundesamt.

Außerdem habe ich noch den durchschnittlichen Auszahlbetrag an BAföG-Empfänger (nur Studenten) in die Situation einbezogen.

Diese Daten übertragen wir in ein Python-Skript, um mit ihnen rechnen und sie visualisieren zu können:

# Bafoeg-Kosten in Mrd Euro
bafoeg_costs = [1109, 1343, 1382, 1414,  
                1488, 1500, 1464, 1561, 1838, 
                1986, 2251, 2382]
 
# Durchschnittlicher Auszahlbetrag (für Studenten)
average_bafoeg = [365, 371, 370, 371, 375, 
                  375, 375, 398, 434, 436, 
                  452, 448]
 
# BIP in Deutschland
bip = [2176.81, 2206.28, 2217.05, 
       2267.58, 2297.82, 2390.2, 
       2510.110, 2558.02, 2456.66, 
       2576.22, 2699.1, 2749.9]
 
# Jahre von 2001 bis 2012
years = range(2001, 2013)

Absolute Zahlen

In einem ersten Schritt könnten wir diese Daten nun folgendermaßen plotten:

import matplotlib.pyplot as plt
 
plt.figure()
plt.xlabel('Jahr')
plt.ylabel('Betrag')
plt.plot(years, bafoeg_costs)
plt.plot(years, bip)
plt.plot(years, average_bafoeg)
plt.legend([u'Öffentliche Ausgaben für BAföG (in Mio Euro)', 'BIP (in Mrd Eu    ro)',
    u'Durchschnittlicher Förderungsbetrag (in Euro)'],
    loc='upper center', bbox_to_anchor=(0.5, 1.10))
plt.show()

BAföG und Wirtschaftsleistung

Das ergibt eine schöne Darstellung, die allerdings trügerisch ist. Will man die Diskussion lenkend beeinflussen – im Sinne der Studentenvertreter – ist diese Grafik sicherlich gut geeignet. Um sich einen guten Überblick darüber zu verschaffen, wie sich BAföG-Zahlungen und Wirtschaftsleistung über die letzten Jahre verhielten, jedoch nicht. Dies liegt daran, dass die Zahlen in ganz verschiedenen Bereichen liegen.

Nehmen wir an, ich verdiene 1000 Euro (zum Glück verdiene ich mehr ;) und spare jeden Monat 10%. Dann spare ich im Moment 100 Euro. Steigt mein Gehalt nun aber auf 1500 Euro, dann werde ich 150 Euro sparen. Zeichnet man nun beide Kurven in eine Grafik, steigt die Einkommenskurve wesentlich steiler an (y = 1000 + 500x) als die Sparkurve (y = 100 + 50x). Die Steigung der Einkommenskurve ist 500, die der Sparkurve nur 50. Deshalb wirkt es so, als würde ich nun viel weniger sparen.

Deshalb eignet sich diese Visualisierung für eine wertneutrale Betrachtung nicht – da niemand verlangen kann, dass die durchschnittliche BAföG-Förderung um eine Million Euro steigt, wenn die wirtschaftsleistung ganz Deutschlands um eine Million Euro steigt.

Prozentuale Veränderung

Abhilfe kann man sich durch die prozentuale Veränderung schaffen. Hierbei berechnen wir die prozentuale Veränderung jedes Werts im Vergleich zum Vorjahr. In solch einer Grafik würden wir sehen, dass sowohl meine Einkommenssteigerung als auch meine Sparquote 50% betrug, ich also relativ immer noch gleich viel spare.

Mit einer kleinen Hilfsfunktion, welche die prozentualen Steigerungen ausrechnet, lässt sich auch dies schnell visualisieren.

from __future__ import division
 
def percentage_changes(values):
    for i in range(0, len(values)-1):
        yield (values[i+1] - values[i]) / values[i] * 100
 
 
plt.figure()
plt.xlabel('Vorjahr')
plt.ylabel(u'Änderung in %')
plt.plot(years[:-1], list(percentage_changes(bafoeg_costs)))
plt.plot(years[:-1], list(percentage_changes(bip)))
plt.plot(years[:-1], list(percentage_changes(average_bafoeg)))
plt.legend([u'Öffentliche Ausgaben für BAföG', 'BIP',
    u'Durchschnittlicher Förderungsbetrag'],
    loc='upper center', bbox_to_anchor=(0.5, 1.10))
plt.show()

BAföG und Wirtschaftsleistung

Wir sehen in dieser Grafik zwei Dinge:

  1. die Steigerungen der öffentlichen Ausgaben für das BAföG liegen fast immer über denen der wirtschaftsleistung
  2. die Steigerungen der Auszahlbeträge selbst liegen fast immer bei 0%, außer im Jahreswechsel 2007/2008 und 2008/2009

Der erste Punkt dürfte an der wachsenden Zahl von Gesamtstudenten liegen. Dadurch steigt natürlich auch, wie man bei bafoeg-rechner.de sieht, die Anzahl an BAföG-Geförderten. Dass die Auszahlbeträge nur in Sprüngen stark steigen, dürfte daran liegen, dass dies von BAföG-Reform-Gesetzen abhängt.

Indexzahl

Leider lässt sich an dieser Grafik nur schwerlich eine Aussage treffen, ob das BAföG hinter den Steigerungen der Wirtschaftsleistung zurückgeblieben ist. Deshalb benötigen wir eine Grafik, die die Änderungen akkumuliert wie unsere erste Grafik, aber trotzdem die prozentuale Veränderung und nicht die absoluten Zahlen betrachtet.

Dazu haben Statistiker die Indexzahlen entworfen. Man benötigt einen einheitlichen Referenzpunkt und berechnet dann die prozentuale Veränderung zu diesem Referenzpunkt. D.h. wir definieren die Zahlenwerte zum Jahr 2001 als einheitliche Referenz. Anschließend plotten wir die Veränderungen zu diesem Basisjahr. Diese Grafik lässt sich für Menschen dann wesentlich leichter erfassen, weil sie sehen, ob die Kurven ungefähr gleich schnell steigen (und vor allem amselben Punkt aufhören) oder nicht.

Mit einer kleinen Funktion, die diese Zahl für uns berechnet, können wir auch diese Grafik ganz leicht erstellen:

def indexed(values):
    index = values[0]
    for value in values:
        yield (value - index) / index * 100
 
plt.figure()
plt.xlabel('Jahr')
plt.ylabel(u'Änderungen zu 2001 in %')
plt.plot(years, list(indexed(bafoeg_costs)))
plt.plot(years, list(indexed(bip)))
plt.plot(years, list(indexed(average_bafoeg)))
plt.legend([u'Öffentliche Ausgaben für BAföG', 'BIP',
    u'Durchschnittlicher Förderungsbetrag'],
    loc='upper center', bbox_to_anchor=(0.5, 1.10))
plt.show()

BAföG und Wirtschaftsleistung

Nun sieht man, dass dank der Änderung zwischen 2007 und 2009 der durchschnittliche Zahlbetrag mit dem BIP mithalten konnte. Die nächste Reform kommt erst wieder 2016, d.h. man kann sich die Kurve etwa linear einige Jahre weiterdenken. Dann wird wieder ein großer Sprung erscheinen und die Kurve könnte wieder mit der BIP-Kurve gleichziehen.

Die Kurve zeigt auch die hohen relativen Steigerungen der öffentlichen Gesamtkosten. Diese Grafik würde man nun heranziehen, wenn man als Bund über die hohen BAföG-Kosten klagen möchte (und von einer “Kostenexplosion” sprechen). Um diese Aussage dann zu relativieren, müsste man vermutlich die Gesamtausgaben des Bundes von 315 Milliarden Euro in die Grafik einbeziehen.

flattr this!

Distribution of torrent files in categories (at kickass.to)

Just a quick chart: Since kickass.to provides its whole archive for download, I was able to analyze which category contains how many torrents.

Most files are movies and TV shows, followed by music and porn. Far behind then come applications, books, anime (which are not counted into TV or movies) and then games.

kickass.to categories

flattr this!

Scrapy: Fix wrong sitemap URLs with custom downloader middleware

On stackoverflow, the topic was discussed, how to solve the problem of some sitemaps having absolute URLs without a scheme. According to RFC this is fine, but as the maintainers of scrapy pointed out, sitemaps require the contents of <loc> to include a scheme (called protocol in the sitemap specs).

So it remains to the programmer of a spider to fix this issue, if he encounters some websites using the wrong format.

Overwriting the default spider does not work so well in this case, because one would have to copy a lot of code. So this seems like a good case for middlewares: Change the response to a valid format without the spider noticing.

The downloader middleware allows us to change the response by returning either a modified or a totally new Response object from process_response.

Thus, it’s rather easy to implement a middleware which takes care of replacing wrongly formatted URLs to the correct ones – at least for the most simplistic cases. I did not implement any sophisticated XML namespace parsing, nor did I implement support for Google’s alternate language pages. The XML namespace parsing would only be important in theory (and for alternate language pages), because the sitemap author could set an additional namespace for the normally default namespace and then the element would not be called <loc> but maybe <sitemap:loc>.

Ignoring these things, one can just use regular expressions to add the scheme where missing.

import re
import urlparse
from scrapy.http import XmlResponse
from scrapy.utils.gz import gunzip, is_gzipped
from scrapy.contrib.spiders import SitemapSpider
 
# downloader middleware
class SitemapWithoutSchemeMiddleware(object):
    def process_response(self, request, response, spider):
        if isinstance(spider, SitemapSpider):
            body = self._get_sitemap_body(response)
 
            if body:
                scheme = urlparse.urlsplit(response.url).scheme
                body = re.sub(r'<loc>\/\/(.+)<\/loc>', r'<loc>%s://\1</loc>' % scheme, body)
                return response.replace(body=body)
 
        return response
 
    def _get_sitemap_body(self, response):
        """Return the sitemap body contained in the given response, or None if the
        response is not a sitemap.
        """
        if isinstance(response, XmlResponse):
            return response.body
        elif is_gzipped(response):
            return gunzip(response.body)
        elif response.url.endswith('.xml'):
            return response.body
        elif response.url.endswith('.xml.gz'):
            return gunzip(response.body)

The newly created middleware can then be added to your project through the settings file (exact setting of course depends on where you saved the middleware).

DOWNLOADER_MIDDLEWARES = {                                                      
    'middlewares.SitemapWithoutSchemeMiddleware': 900
}

flattr this!