[reportlab-users] Set verticalbarchart label x, y positions depending on value

Matt Bartolome mattxbart at gmail.com
Wed Aug 22 11:25:24 EDT 2018


Thank you so much for the working code and suggestions. I've almost got it
now... What I also want to do is hide a duplicate vertical value. Is there
a property on bl that will hide it, like bl.visible = 0 or something like
that?

# fix position of stacked labels
self.chart.valueAxis.setPosition(self.chart.x, self.chart.y,
self.chart.height)
self.chart._getConfigureData()
self.chart.valueAxis.configure(self.chart._configureData)

for i, d in enumerate(self.chart.data):
    v_collision = []
    for j, v in enumerate(d):
        if v is None:
            continue
        h = v * self.chart.valueAxis._scaleFactor
        bl = self.chart.barLabels[(i, j)]
        if v in v_collision:
            # I want to hide this label because it shows right on top of
the other stacked label, basically presenting as a bold value because they
are on top of each other
            continue
        if h < 10.0:
            # this sets the label right on top of the stacked bar chart
with a tiny space, great
            bl.boxAnchor = 'sw'
            bl.dy = 1
        v_collision.append(v)

On Mon, Aug 20, 2018 at 1:49 PM Kostadin Atanasov <
kostadin.atanasov at gmail.com> wrote:

> I usually calculate the value of each series (segment in the bar) as a %
> of the max Y scale value and use it to decide whether to display the label
> at all (the label is still in absolute units, the % is only for decision).
> My cutoff is around 3 or 4%. Typically if the value is so low nobody is
> very worried that the label is missing. If you have many cases of values
> below 4% this means that your bar is very fragmented - then you have a
> different problem - probably bar is not the best visualisation.
>
> Kostadin Atanasov
>
> ------------------------------
> *From:* reportlab-users <reportlab-users-bounces at lists2.reportlab.com> on
> behalf of Robin Becker <robin at reportlab.com>
> *Sent:* Monday, August 20, 2018 5:38:10 PM
> *To:* reportlab-users
> *Subject:* Re: [reportlab-users] Set verticalbarchart label x, y
> positions depending on value
>
> On 18/08/2018 00:14, Matt Bartolome wrote:
> > Hi, I have a stacked vertical bar chart where I need to either manually
> > place labels or iterate over the existing labels and move them based on
> > their position (crossing my fingers that there is a simpler way). The
> > problem I have is that my stacked bar chart has overlapping labels when
> the
> > y values are close to zero because of the scale of my chart.
> >
> > My barLabels settings are like so:
> >
> > self.chart.barLabelFormat = lambda x: '${0}'.format(x) if x > 0 else None
> > self.chart.barLabels.boxAnchor = 'w'
> > self.chart.barLabels.boxFillColor = None
> > self.chart.barLabels.boxStrokeColor = None
> > self.chart.barLabels.fontName = fontName
> > self.chart.barLabels.fontSize = 6
> > self.chart.barLabels.dy = 5
> > self.chart.barLabels.dx = -8
> > self.chart.barLabels.boxTarget = 'mid'
> >
> > I was hoping there was a setting to avoid overlap, but if that doesn't
> > exist I would like to loop over the x,y positions of the existing labels
> > and create my own simple labels to replace them but I can't figure out
> how
>
> I don't think we have a magic way to get the bar labels to not overlap;
> normally people want stacked bar labels to be inside the
> bar, but as you observe when bars become short there's no place to put the
> label inside.
>
>
> However, here is some code I have used in the past
>
> def label_fixer(chart,colors,needed):
>         vA = chart.valueAxis
>         vA.setPosition(chart.x, chart.y, chart.height)
>         chart._getConfigureData()
>         vA.configure(chart._configureData)
>
>         barLabels = chart.barLabels
>         for i,d in enumerate(chart.data):
>                 for j, v in enumerate(d):
>                         if v is None: continue
>                         h = v * vA._scaleFactor
>                         bl = barLabels[(i,j)]
>                         if needed<=h:
>                                 bl.boxAnchor = 'n'
>                                 bl.fillColor = barLabels.fillColor
>                                 bl.dx = bl.dy = 0
>                         elif v>0:
>                                 bl.fillColor = colors[i]
>                                 if not i:
>                                         bl.boxAnchor = 'nw'
>                                         bl.dx = chart.barWidth * 0.5
>                                 else:
>                                         bl.boxAnchor = 's'
>
>
>
> and in the chart code getContents method
>
> label_fixer(chart=chart,needed=1.2*chart.barLabels.fontSize+4,
> colors=[self._orange,self._grey])
>
>
> this was for a simple chart where the top of two stacked bars was likely
> to be too small. If that happens the bar is moved up so
> is outside. If the lower bar needs a fix we moved the label to the side
> and downwards (bl.boxAnchor = 'nw'),
>
> The main idea is to get the scaling and then you can check how tall the
> bar is going to be. Then you need a strategy for changing
> the default position.
>
>
> > to do that.
> >
> > Thanks,
> > Matt
> >
> ........
> --
> Robin Becker
> _______________________________________________
> reportlab-users mailing list
> reportlab-users at lists2.reportlab.com
> https://pairlist2.pair.net/mailman/listinfo/reportlab-users
> _______________________________________________
> reportlab-users mailing list
> reportlab-users at lists2.reportlab.com
> https://pairlist2.pair.net/mailman/listinfo/reportlab-users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://pairlist2.pair.net/pipermail/reportlab-users/attachments/20180822/3749deeb/attachment.html>


More information about the reportlab-users mailing list