10000 Plotting series of bar charts using plt.subplots() based on data in Pandas dataframe fails when bars are aligned center · Issue #8767 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content
Plotting series of bar charts using plt.subplots() based on data in Pandas dataframe fails when bars are aligned center #8767
Closed
@lvphj

Description

@lvphj

Bug report

Bug summary

Plotting a series of bar charts from a Pandas dataframe works fine when align='edge' but fails when align='center' unless dataframe variables are set to .values.

Code for reproduction

The following code works fine:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({'year':[2014]*12 + [2015]*12 + [2016]*12,
                   'month': list(range(1,13))*3,
                   'percent': np.random.uniform(0.1,0.5,36)})

fig, axArr = plt.subplots(3,figsize = [8,10],sharex = True,sharey = True)

# Keep track of which year to plot, starting with first year in dataset.
currYear = df['year'].min()

# Step through each subplot
for ax in axArr:
    
    # Plot the data
    rects = ax.bar(df.loc[df['year'] == currYear,'month'],
                   df.loc[df['year'] == currYear,'percent'],
                   align = 'edge')

    currYear = currYear + 1

...but replacing align='center' causes error (KeyError: 0):

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({'year':[2014]*12 + [2015]*12 + [2016]*12,
                   'month': list(range(1,13))*3,
                   'percent': np.random.uniform(0.1,0.5,36)})

fig, axArr = plt.subplots(3,figsize = [8,10],sharex = True,sharey = True)

# Keep track of which year to plot, starting with first year in dataset.
currYear = df['year'].min()

# Step through each subplot
for ax in axArr:
    
    # Plot the data
    rects = ax.bar(df.loc[df['year'] == currYear,'month'],
                   df.loc[df['year'] == currYear,'percent'],
                   align = 'center')

    currYear = currYear + 1

When align = 'center', the code can be made to work by setting the dataframe data to 'values':

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({'year':[2014]*12 + [2015]*12 + [2016]*12,
                   'month': list(range(1,13))*3,
                   'percent': np.random.uniform(0.1,0.5,36)})

fig, axArr = plt.subplots(3,figsize = [8,10],sharex = True,sharey = True)

# Keep track of which year to plot, starting with first year in dataset.
currYear = df['year'].min()

# Step through each subplot
for ax in axArr:
    
    # Plot the data
    rects = ax.bar(df.loc[df['year'] == currYear,'month'].values,
                   df.loc[df['year'] == currYear,'percent'].values,
                   align = 'center')

    currYear = currYear + 1

Actual outcome

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-39-a3ac948488e0> in <module>()
     18     rects = ax.bar(df.loc[df['year'] == currYear,'month'],
     19                    df.loc[df['year'] == currYear,'percent'],
---> 20                    align = 'center')
     21 
     22     currYear = currYear + 1

/Users/philjones/Documents/python_projects/python34_example_environment_2015-10-30/env3/lib/python3.4/site-packages/matplotlib/__init__.py in inner(ax, *args, **kwargs)
   1896                     warnings.warn(msg % (label_namer, func.__name__),
   1897                                   RuntimeWarning, stacklevel=2)
-> 1898             return func(ax, *args, **kwargs)
   1899         pre_doc = inner.__doc__
   1900         if pre_doc is None:

/Users/philjones/Documents/python_projects/python34_example_environment_2015-10-30/env3/lib/python3.4/site-packages/matplotlib/axes/_axes.py in bar(self, left, height, width, bottom, **kwargs)
   2103         if align == 'center':
   2104             if orientation == 'vertical':
-> 2105                 left = [left[i] - width[i] / 2. for i in xrange(len(left))]
   2106             elif orientation == 'horizontal':
   2107                 bottom = [bottom[i] - height[i] / 2.

/Users/philjones/Documents/python_projects/python34_example_environment_2015-10-30/env3/lib/python3.4/site-packages/matplotlib/axes/_axes.py in <listcomp>(.0)
   2103         if align == 'center':
   2104             if orientation == 'vertical':
-> 2105                 left = [left[i] - width[i] / 2. for i in xrange(len(left))]
   2106             elif orientation == 'horizontal':
   2107                 bottom = [bottom[i] - height[i] / 2.

/Users/philjones/Documents/python_projects/python34_example_environment_2015-10-30/env3/lib/python3.4/site-packages/pandas/core/series.py in __getitem__(self, key)
    601         key = com._apply_if_callable(key, self)
    602         try:
--> 603             result = self.index.get_value(self, key)
    604 
    605             if not is_scalar(result):

/Users/philj
5F8C
ones/Documents/python_projects/python34_example_environment_2015-10-30/env3/lib/python3.4/site-packages/pandas/indexes/base.py in get_value(self, series, key)
   2167         try:
   2168             return self._engine.get_value(s, k,
-> 2169                                           tz=getattr(series.dtype, 'tz', None))
   2170         except KeyError as e1:
   2171             if len(self) > 0 and self.inferred_type in ['integer', 'boolean']:

pandas/index.pyx in pandas.index.IndexEngine.get_value (pandas/index.c:3323)()

pandas/index.pyx in pandas.index.IndexEngine.get_value (pandas/index.c:3026)()

pandas/index.pyx in pandas.index.IndexEngine.get_loc (pandas/index.c:4009)()

pandas/src/hashtable_class_helper.pxi in pandas.hashtable.Int64HashTable.get_item (pandas/hashtable.c:8146)()

pandas/src/hashtable_class_helper.pxi in pandas.hashtable.Int64HashTable.get_item (pandas/hashtable.c:8090)()

KeyError: 0

Expected outcome

Expected output is a series of 3 bar charts, 1 per year represented in the dataframe, stacked one above the other.

Code used to work on Matplotlib 1.4.3 (except there were issues with spacing of y axis tick labels).

Matplotlib version

  • Operating System: MacOS 10.11.6
  • Matplotlib Version: 2.0.2
  • Python Version: 3.4.1
  • Jupyter Version (if applicable): 1.0.0
  • Other Libraries: Numpy v1.13.0; Pandas 0.19.2

All libraries installed using pip.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Difficulty: Easyhttps://matplotlib.org/devdocs/devel/contribute.html#good-first-issues

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0