Search code examples
pythondjangochartsreportlab

Adding date labels to a reportlab LinePlot chart


I am using reportlab to generate a LinePlot chart. I can't seem to get non numeric labels for the X axis. enter image description here

Does anyone have any ideas?

This is my Lineplot chart class (note: im donig some calculations and setup outside this class, but you get the gist

import reportlab
from advisor.charting.Font import Font

from reportlab.lib.colors import Color, HexColor
from reportlab.lib.pagesizes import cm, inch
from reportlab.graphics.charts.legends import Legend
from reportlab.graphics.charts.textlabels import Label
from reportlab.graphics.charts.linecharts import HorizontalLineChart
from reportlab.graphics.charts.lineplots import LinePlot
from reportlab.graphics.shapes import Drawing, String, _DrawingEditorMixin
from reportlab.graphics.widgets.markers import makeMarker


class TacticalAugLineGraph(_DrawingEditorMixin, Drawing):       
    def __init__(self, width=100, height=110, legend=False, *args, **kw):
        apply(Drawing.__init__, (self, width, height) + args, kw)

        chartFont = Font('Gotham-Bold')

        self._add(self, LinePlot(), name='chart', validate=None, desc=None)
        self.chart._inFill = 1
        self.chart.x                = 20
        self.chart.y                = 15
        self.chart.width        = 85
        self.chart.height   = 95

        #self.chart.lineLabelFormat = '%d%%'
        self.chart.yValueAxis.valueMin = 0
        self.chart.yValueAxis.valueMax = 100
        self.chart.yValueAxis.valueStep = 10

    def apply_colors(self, colors):

        self.chart.lines[0].strokeColor = colors[0]
        self.chart.lines[1].strokeColor = colors[1]
        self.chart.lines[2].strokeColor = colors[2]
        self.chart.lines[3].strokeColor = colors[3]

Solution

  • I produced a simple example that you could test. The result could look like this: enter image description here

    #!/usr/bin/python
    from reportlab.graphics.charts.lineplots import LinePlot
    from reportlab.graphics.shapes import Drawing
    from reportlab.lib import colors
    from random import randint
    from datetime import date, timedelta
    
    # Generate some testdata
    data = [
        [(x,randint(90,100)) for x in range(0,2001,100)],
        [(x,randint(30,80)) for x in range(0,2001,100)],
        [(x,randint(5,20)) for x in range(0,2001,100)],
        ]
    
    # Create the drawing and the lineplot
    drawing = Drawing(400, 200)
    lp = LinePlot()
    lp.x = 50
    lp.y = 50
    lp.height = 125
    lp.width = 300
    lp._inFill = 1
    lp.data = data
    for i in range(len(data)):
        lp.lines[i].strokeColor = colors.toColor('hsl(%s,80%%,40%%)'%(i*60))
    
    # Specify where the labels should be
    lp.xValueAxis.valueSteps = [5, 500, 1402, 1988]
    # Create a formatter that takes the value and format it however you like.
    def formatter(val):
        #return val
        #return 'x=%s'%val
        return (date(2010,1,1) + timedelta(val)).strftime('%Y-%m-%d')
    
    # Use the formatter
    lp.xValueAxis.labelTextFormat = formatter
    drawing.add(lp)
    
    from reportlab.graphics import renderPDF
    renderPDF.drawToFile(drawing, 'example.pdf', 'lineplot with dates')
    

    In the formatter there is 2 alternative return statements that you could play with to get a better grip on it.

    Of course if the data on the x-axis is dates to begin with there need not be any formatter, in that case you could just specify where the labels should be (if you are not satisfied with the default positioning).

    The example above borrows the ideas from page 105 in the reportlab documentation.

    Good luck :)