Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

plotting stacked barplots on a pandas dataframe

Tags:

python

pandas

This is my first attempt at playing with Pandas library after attending Wesley's tutorial at pycon.

After poking around a bit with the dataframe I am glad I was able to massage the data in the way I wanted but having trouble in plotting it. I guess it also points to my naiveness with the matplotlib library.

What I have is pandas Series object with the following data. I would like to plot as a barplot with col 1 ('file') as the labels oriented vertically.

sample data here:
http://pastebin.com/y2w0uJPQ 
like image 947
Abhi Avatar asked Mar 30 '12 06:03

Abhi


People also ask

How do you plot a bar chart from a data frame?

Plotting Bar charts using pandas DataFrame: The bar() method draws a vertical bar chart and the barh() method draws a horizontal bar chart. The bar() and barh() of the plot member accepts X and Y parameters. By default, X takes the index of the DataFrame and all the numeric columns are drawn as Y.

How do you plot Barh?

A horizontal bar plot is a plot that presents quantitative data with rectangular bars with lengths proportional to the values that they represent. A bar plot shows comparisons among discrete categories. One axis of the plot shows the specific categories being compared, and the other axis represents a measured value.


Video Answer


2 Answers

I've just implemented a stacked bar plot function in the git repository for pandas, will be part of the upcoming 0.7.3 release:

In [7]: df
Out[7]: 
          a         b         c
0  0.425199  0.564161  0.727342
1  0.174849  0.071170  0.679178
2  0.224619  0.331846  0.468959
3  0.654766  0.189413  0.868011
4  0.617331  0.715088  0.387540
5  0.444001  0.069016  0.417990
6  0.203908  0.689652  0.227135
7  0.382930  0.874078  0.571042
8  0.658687  0.493955  0.245392
9  0.758986  0.385871  0.455357

In [8]: df.plot(kind='barh', stacked=True)

Stacked Bar Plot

It properly handles positive and negative values (stacking negative values below the origin and positive values above)

like image 179
Wes McKinney Avatar answered Sep 28 '22 06:09

Wes McKinney


Recently I have programmed a function to do something very similar. Here you have a simplified version:

from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.colors import colorConverter
import matplotlib.lines as mlines
import matplotlib

def _add_legend(axes):
    'It adds the legend to the plot'
    box = axes.get_position()
    axes.set_position([box.x0, box.y0, box.width * 0.9, box.height])

    handles, labels = axes.get_legend_handles_labels()

    # sort by the labels
    handel_lables = sorted(zip(handles, labels), key=operator.itemgetter(1))
    handles, labels = zip(*handel_lables)

    axes.legend(handles, labels, bbox_to_anchor=(1.05, 1), loc=2,
                borderaxespad=0., prop={'size':LEGEND_FONT_SIZE},
                fancybox=True, numpoints=1)


def stacked_bars(matrix, fhand, bar_colors=None):
    'It draws stacked columns'
    bar_width = 1
    fig = Figure(figsize=FIGURE_SIZE)
    canvas = FigureCanvas(fig)
    axes = fig.add_subplot(111)
    nrows, ncols = matrix.shape

    bar_locs = range(0, nrows)
    cum_heights = numpy.zeros(nrows)
    for col_index, (col_name, column) in enumerate(matrix.iteritems()):
        color = bar_colors[col_index] if bar_colors is not None else None
        values = column.values
        axes.bar(bar_locs, values, color=color, bottom=cum_heights,
                 width=bar_width, label=col_name)
        cum_heights += values
    min_y, max_y = axes.get_ylim()

    #bar labels
    axes.set_xticks([l + bar_width * 0.4 for l in bar_locs])
    labels = axes.set_xticklabels([str(l) + '  ' for l in matrix.index.values],
                                  fontsize=AXIS_LABELS_FONT_SIZE)
    for label in labels:
        label.set_rotation('vertical')

    _add_legend(axes)

    canvas.print_figure(fhand, format=_get_format_from_fname(fhand.name))
fhand.flush()

I hope it helps you to get an idea.

like image 21
Jose Blanca Avatar answered Sep 28 '22 08:09

Jose Blanca