pygal icon indicating copy to clipboard operation
pygal copied to clipboard

merge line and bar

Open pimpampoum opened this issue 11 years ago • 10 comments

Is it possible to merge two charts, for instance a Bar chart and an XY chart on the same svg ?

pimpampoum avatar Jul 04 '13 12:07 pimpampoum

As of now no. But nothing is impossible !

paradoxxxzero avatar Jul 04 '13 14:07 paradoxxxzero

Hi there, this is just to support this feature request. I really like pygal a lot but have specific use cases where this would be convenient. For example, when I want to show the absolute count for several items using (ordered) bars and an axis with counts, but also a line showing the cumulated proportion of the total sum of counts (using a secondary axis with percentages rather than counts).

christofs avatar Jun 13 '16 14:06 christofs

Yes and it would be a good opportunity to refactor secondary series.

paradoxxxzero avatar Jun 13 '16 14:06 paradoxxxzero

I managed to did it by using a nasty hack but I write down the code here, it can help someone:

Instead of doing chart = Bar(), just do chart = LineBar().

from __future__ import division
from pygal.graph.graph import Graph

# Import Bar and Line chart
from pygal.graph.bar import Bar
from pygal.graph.line import Line

# Create a class extending Graph
class LineBar(Graph):
    # All the series are bar except the last which is line
    # It was my use case but you can change it depending on your need
    def _plot(self):
        for i, serie in enumerate(self.series, 1):
            if i == len(self.series):
                self.line(serie)
            else:
                self.bar(serie)

# Here we add the necessary properties to LineBar
# It's an ugly trick but it does the job and that's why I love python!

# Add bar properties
LineBar.bar = Bar.bar
LineBar._compute = Bar._compute
LineBar._bar = Bar._bar
LineBar._series_margin = Bar._series_margin
LineBar._serie_margin = Bar._serie_margin
LineBar._tooltip_and_print_values = Bar._tooltip_and_print_values

# Add line properties
LineBar.line = Line.line
LineBar._fill = Line._fill
LineBar._self_close = False

Good luck!

realitix avatar Nov 28 '16 10:11 realitix

@realitix how to use LineBar?

Yuliang-Lee avatar Dec 08 '16 07:12 Yuliang-Lee

@Yuliang-Lee

chart = LineBar(style=style)
chart.title = "Stat"
chart.x_labels = ['0', '1', '2', '3', '4']
chart.add('First Bar', [1, 2, 3, 4, 5])
chart.add('Second bar', [5, 4, 3, 2, 1])
chart.add('Line stat', [4, 2, 0, 5, 4])
chart.render_to_file(''/tmp/out.svg")

realitix avatar Dec 08 '16 14:12 realitix

@realitix Yours does not handle secondary. And you could extend LineBar from Line and Bar as LineBar(Bar, Line)

ebsaral avatar Sep 18 '17 15:09 ebsaral

Indeed @ebsaral, like I said it's a ugly hack without thinking a lot. ;-)

realitix avatar Sep 18 '17 15:09 realitix

@realitix ... chart = LineBar(style=style) chart.title = "Stat" chart.x_labels = ['0', '1', '2', '3', '4'] chart.add('First Bar', [1, 2, 3, 4, 5]) chart.add('Second bar', [5, 4, 3, 2, 1]) chart.add('Line stat', [4, 2, 0, 5, 4]) chart.render_to_file(''/tmp/out.svg")

But, I am getting following error TypeError: init() takes at most 2 arguments (3 given) ; After this I had tried, chart = LineBar(Line) AttributeError: 'LineBar' object has no attribute 'style'

I am not sure how to use it, could you please help me. thank you

kurkutesa avatar Feb 07 '18 06:02 kurkutesa

See also #516. #516 uses Line and Bar and not Bar and XY, but I think extending the example to include XY should be pretty straightforward.

rouilj avatar Jun 02 '21 17:06 rouilj