1

I'm looking for a very simple example of taking a Django QuerySet and then generating a graph using matplotlib. All the examples I've found have hard-coded data values or they don't really explain what they are doing. I thought this would be a good question for others as well.

Let me set the stage with a very simple example so this is very easy to follow for me and for other n00bs. ;-)

class Animals(models.Model):
    cats = models.PositiveSmallIntegerField
    dogs = models.PositiveSmallIntegerField
    created = created = models.DateTimeField(auto_now_add=True)

datatograph = Animals.objects.all()

How do I get datatograph into the right format so I can pass it to matplotlib and end up with two an X axis of integers, y axis of dates and a line for dogs and a line for cats.

Thank you!

3
  • You need to show a bit more effort in what you've already have achieved. You can perform three queries for each field separately, or loop over datatograph and extract the invidiual elements, putting them in their own array. Commented Aug 15, 2015 at 2:19
  • I've achieved nothing, because I don't understand why this is more complicated than passing the queryset to a library and specifying which columns go on which access. This is a very powerful but confusing library. Commented Aug 15, 2015 at 6:33
  • 1
    Because matplotlib is not Django: querysets are unique to Django, matplotlib won't understand them. You'll have to transform the queryset into something matplotlib can work with. Commented Aug 15, 2015 at 6:36

2 Answers 2

5

First let's create some Animals objects (I removed the auto_now_add from your model to make this simpler):

from random import randint
from datetime import timedelta
from django.utils import timezone

from animals.models import Animals

animals = []
base_date = timezone.now().replace(day=1)
for i in range(0, 10):
    dt = base_date + timedelta(days=i)
    animals.append(Animals(
        cats=randint(0, 100),
        dogs=randint(0, 100),
        created=dt))

Animals.objects.bulk_create(animals)

Then we could do something like this:

from django.utils import timezone
from matplotlib import pyplot
from animals.models import Animals

# Fetch the data
begin_date = timezone.now().replace(
    day=1, hour=0, minute=0, second=0, microsecond=0)
end_date = begin_date.replace(day=11)
datatograph = Animals.objects.filter(
    created__gte=begin_date, created__lt=end_date
).values('cats', 'dogs', 'created')

# Transform the data
cats = list(map(lambda d: d['cats'], datatograph))
dogs = list(map(lambda d: d['dogs'], datatograph))
dates = list(map(lambda d: d['created'].day, datatograph))

# Set up the plots
cats_plot = pyplot.plot(dates, cats, 'bo-', label='Cats')[0]
dogs_plot = pyplot.plot(dates, dogs, 'ro-', label='Dogs')[0]

# Set up the axis
pyplot.axis([min(dates), max(dates), min(cats + dogs), max(cats + dogs)])
pyplot.xlabel('day')

# Set up the legend and title
pyplot.legend(handles=[cats_plot, dogs_plot])
pyplot.title('Animals')

# Show the plot
pyplot.show()

Which creates a chart like this.

Sign up to request clarification or add additional context in comments.

1 Comment

I had a hard time understanding your answer because of the use of the lambda which I found a little hard to follow. I asked my friend to explain it and the secret sauce for my brain, was to know that what we're doing is converting each of the three columns in the ORM to an array (LIST in Python)
1

I had a hard time understanding your answer because of the use of the lambda which I found a little hard to follow. I asked my friend to explain it and the secret sauce for my brain, was to know that what we're doing is converting each of the three columns in the ORM to an array (LIST in Python). I think this is a simpler answer for the beginner (like me).

class Animals(models.Model):
cats = models.PositiveSmallIntegerField
dogs = models.PositiveSmallIntegerField
created = created = models.DateTimeField(auto_now_add=True)

import matplotlib.pyplot as plt

datatograph = Animals.objects.all()

for a in datatograph
    catslist = catslist + [a.cats]
    dogslist = dogslist + [a.cats]
    dates = dates + [a.created]
plt.plot(dates, catslist)
plt.plot(dates, dogslist)
plt.show() # Pops up a dialog with the graph, se plt.savefig(filename.ext) to save in .ext format like .png
plt.close()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.