Re: Set verticalbarchart label x, y positions depending on value

Matt Bartolome <[email protected]>
Newsgroups gmane.comp.python.reportlab.user
Message-ID <CAL9O_mM7W-5F09jw=sCC_YYbzrBtzcWyoZE=LO=29rkSEBce7w@mail.gmail.com>
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 <
[email protected]> 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 <[email protected]> on
> behalf of Robin Becker <[email protected]>
> *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
> [email protected]
> https://pairlist2.pair.net/mailman/listinfo/reportlab-users
> _______________________________________________
> reportlab-users mailing list
> [email protected]
> https://pairlist2.pair.net/mailman/listinfo/reportlab-users
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.