blog.dbrgn.ch

Plot Registered Django Users with Matplotlib

written on Thursday, September 26, 2013 by

Sometimes you want to see the number of registered users in your Django website over time. Fortunately Django stores the registration date of a user model instance in the date_joined field, so we can plot it.

An example plot of user registrations.

Prerequisites

You need an installation of numpy and matplotlib. You can install the libraries using pip:

$ pip install numpy
$ pip install matplotlib

It is important that you install numpy before you install matplotlib, otherwise compiling the latter won't work. You can also use your system package manager to install them instead, if you prefer that.

Adding a Management Command

Now create a new Django management command. We could also do this as a standalone script, but by creating a management command we have easier access to the database.

$ mkdir -p <myapp>/management/commands
$ touch <myapp>/management/__init__.py
$ touch <myapp>/management/commands/__init__.py
$ touch <myapp>/management/commands/plot_user_registrations.py

Now add the following code to your plot_user_registrations.py file:

from optparse import make_option

from django.core.management.base import BaseCommand
from django.contrib.auth import get_user_model

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.dates import date2num


class Command(BaseCommand):
    help = 'Plot user registrations. Use --save option to save the plot to a png file.'
    option_list = BaseCommand.option_list + (
        make_option('--save', action='store',
            dest='save', help='Save the graph as a png to the specified location'),
    )

    def handle(self, *args, **options):
        # Get user join dates
        User = get_user_model()
        datetimes = User.objects.values_list('date_joined', flat=True) \
                                .order_by('date_joined')
        dates = map(lambda d: d.date(), datetimes)

        # Get some auxilliary values
        min_date = date2num(dates[0])
        max_date = date2num(dates[-1])
        days = max_date - min_date + 1

        # Initialize X and Y axes
        x = np.arange(min_date, max_date + 1)
        y = np.zeros(days)

        # Iterate over dates, increase registration array
        for date in dates:
            index = int(date2num(date) - min_date)
            y[index] += 1
        y_sum = np.cumsum(y)

        # Plot
        plt.plot_date(x, y_sum, xdate=True, ydate=False, ls='-', ms=0, color='#16171E')
        plt.fill_between(x, 0, y_sum, facecolor='#D0F3FF')
        plt.title('Registered Users')
        plt.rc('font', size=8)
        if options['save']:
            plt.savefig(options['save'])
        else:
            plt.show()

Usage

Now you can call your new management command:

$ python manage.py plot_user_registrations

This will open a new window containing the plot. You can also save it to a png file instead:

$ python manage.py plot_user_registrations --save users.png

If you want, you can tweak the matplotlib configuration in order to change the plot style / colors / etc. If you find some nice improvements, feel free to leave a comment below!

This entry was tagged datavis, django, matplotlib and python