Horizontal bar chart with log x-axis, no filled boxes

I'm running into something odd in Matplotlib 1.1. In drawing a horizontal bar chart (barh), if the x-axis scale is set to log, the rectangles are not drawn and filled; I just get small ticks at the right-hand position where the rectangle should end. Interestingly, if I add a second, stacked barh to the same axes, that second set of rectangles draws fine, even though the first does not.

If I simply comment out the call setting the x axis to log, it works properly.

Any thoughts?

···

--
-- Christophe Pettus
   xof@...3912...

Does everything work correctly if it is vertical? In other words, use bar() and set the y-axis to log scale? An example script would be useful.

Ben Root

···

On Thu, Jan 12, 2012 at 9:03 AM, Christophe Pettus <xof@…713…912…> wrote:

I’m running into something odd in Matplotlib 1.1. In drawing a horizontal bar chart (barh), if the x-axis scale is set to log, the rectangles are not drawn and filled; I just get small ticks at the right-hand position where the rectangle should end. Interestingly, if I add a second, stacked barh to the same axes, that second set of rectangles draws fine, even though the first does not.

If I simply comment out the call setting the x axis to log, it works properly.

Any thoughts?

No, it doesn't appear to work as a vertical bar chart, either.

I've attached a test case below. The results I get running it with the X-axis as log are:

  http://thebuild.com/matlabtest/matlabtest-log.pdf

Commenting out the call to ax.set_xscale('log') gives me:

  http://thebuild.com/matlabtest/matlabtest.pdf

Thanks!

···

On Jan 12, 2012, at 7:38 AM, Benjamin Root wrote:

Does everything work correctly if it is vertical? In other words, use bar() and set the y-axis to log scale? An example script would be useful.

--

import numpy as np
import matplotlib
from matplotlib.font_manager import FontProperties

import random

matplotlib.use('PDF')

import matplotlib.pyplot as plot

small_font = FontProperties()
small_font.set_size('xx-small')

ind = np.arange(20)

label = [ str(r) for r in ind ]
data1 = [ float(random.random()*100000000) for r in ind ]
data2 = [ float(random.random()*100000000) for r in ind ]

width = 0.25

fig = plot.figure()
ax = fig.add_subplot(111)

ax.set_title('Table Title')
ax.set_xlabel('X Label')

ax.barh(ind, data1, width, linewidth=0, color='blue')
ax.barh(ind, data2, width, left=data1, linewidth=0, color='yellow')
ax.set_yticks(ind + width/2)
ax.set_yticklabels(label, fontproperties=small_font)
ax.set_xscale('log')

plot.savefig('matlabtest-log.pdf')

--
-- Christophe Pettus
   xof@...3912...

Does everything work correctly if it is vertical? In other words, use bar() and set the y-axis to log scale? An example script would be useful.

No, it doesn’t appear to work as a vertical bar chart, either.

I’ve attached a test case below. The results I get running it with the X-axis as log are:

    [http://thebuild.com/matlabtest/matlabtest-log.pdf](http://thebuild.com/matlabtest/matlabtest-log.pdf)

Commenting out the call to ax.set_xscale(‘log’) gives me:

    [http://thebuild.com/matlabtest/matlabtest.pdf](http://thebuild.com/matlabtest/matlabtest.pdf)

Thanks!

import numpy as np

import matplotlib

from matplotlib.font_manager import FontProperties

import random

matplotlib.use(‘PDF’)

import matplotlib.pyplot as plot

small_font = FontProperties()

small_font.set_size(‘xx-small’)

ind = np.arange(20)

label = [ str® for r in ind ]

data1 = [ float(random.random()*100000000) for r in ind ]

data2 = [ float(random.random()*100000000) for r in ind ]

width = 0.25

fig = plot.figure()

ax = fig.add_subplot(111)

ax.set_title(‘Table Title’)

ax.set_xlabel(‘X Label’)

ax.barh(ind, data1, width, linewidth=0, color=‘blue’)

ax.barh(ind, data2, width, left=data1, linewidth=0, color=‘yellow’)

ax.set_yticks(ind + width/2)

ax.set_yticklabels(label, fontproperties=small_font)

ax.set_xscale(‘log’)

plot.savefig(‘matlabtest-log.pdf’)

– Christophe Pettus

Isn’t this just because zero isn’t defined in log scale? The second set of data plots fine because it doesn’t start at zero, but it isn’t obvious what to do with the first set of data. If you just want to make this work, you can set the left parameter of the first barh call to some constant; for example:

origin = 10**np.floor(np.log10(np.min(data1)))

ax.barh(ind, data1, width, left=origin, linewidth=0, color=‘blue’)

-Tony

···

On Thu, Jan 12, 2012 at 11:39 AM, Christophe Pettus <xof@…83…3912…> wrote:

On Jan 12, 2012, at 7:38 AM, Benjamin Root wrote:

Right, but I could have sworn that we got this fixed at some point. There is logic in the bar() function to detect logscale and handle it appropriately. But I don’t know what is not working here.

Ben Root

···

On Thu, Jan 12, 2012 at 11:04 AM, Tony Yu <tsyu80@…1896…> wrote:

On Thu, Jan 12, 2012 at 11:39 AM, Christophe Pettus <xof@…3912…> wrote:

On Jan 12, 2012, at 7:38 AM, Benjamin Root wrote:

Does everything work correctly if it is vertical? In other words, use bar() and set the y-axis to log scale? An example script would be useful.

No, it doesn’t appear to work as a vertical bar chart, either.

I’ve attached a test case below. The results I get running it with the X-axis as log are:

    [http://thebuild.com/matlabtest/matlabtest-log.pdf](http://thebuild.com/matlabtest/matlabtest-log.pdf)

Commenting out the call to ax.set_xscale(‘log’) gives me:

    [http://thebuild.com/matlabtest/matlabtest.pdf](http://thebuild.com/matlabtest/matlabtest.pdf)

Thanks!

import numpy as np

import matplotlib

from matplotlib.font_manager import FontProperties

import random

matplotlib.use(‘PDF’)

import matplotlib.pyplot as plot

small_font = FontProperties()

small_font.set_size(‘xx-small’)

ind = np.arange(20)

label = [ str® for r in ind ]

data1 = [ float(random.random()*100000000) for r in ind ]

data2 = [ float(random.random()*100000000) for r in ind ]

width = 0.25

fig = plot.figure()

ax = fig.add_subplot(111)

ax.set_title(‘Table Title’)

ax.set_xlabel(‘X Label’)

ax.barh(ind, data1, width, linewidth=0, color=‘blue’)

ax.barh(ind, data2, width, left=data1, linewidth=0, color=‘yellow’)

ax.set_yticks(ind + width/2)

ax.set_yticklabels(label, fontproperties=small_font)

ax.set_xscale(‘log’)

plot.savefig(‘matlabtest-log.pdf’)

– Christophe Pettus

Isn’t this just because zero isn’t defined in log scale? The second set of data plots fine because it doesn’t start at zero, but it isn’t obvious what to do with the first set of data. If you just want to make this work, you can set the left parameter of the first barh call to some constant; for example:

origin = 10**np.floor(np.log10(np.min(data1)))

ax.barh(ind, data1, width, left=origin, linewidth=0, color=‘blue’)

-Tony

Ahh, I didn’t know this. It looks like setting log=True in barh works.

-Tony

···

On Thu, Jan 12, 2012 at 12:14 PM, Benjamin Root <ben.root@…1304…> wrote:

On Thu, Jan 12, 2012 at 11:04 AM, Tony Yu <tsyu80@…287…> wrote:

On Thu, Jan 12, 2012 at 11:39 AM, Christophe Pettus <xof@…3912…> wrote:

On Jan 12, 2012, at 7:38 AM, Benjamin Root wrote:

Does everything work correctly if it is vertical? In other words, use bar() and set the y-axis to log scale? An example script would be useful.

No, it doesn’t appear to work as a vertical bar chart, either.

I’ve attached a test case below. The results I get running it with the X-axis as log are:

    [http://thebuild.com/matlabtest/matlabtest-log.pdf](http://thebuild.com/matlabtest/matlabtest-log.pdf)

Commenting out the call to ax.set_xscale(‘log’) gives me:

    [http://thebuild.com/matlabtest/matlabtest.pdf](http://thebuild.com/matlabtest/matlabtest.pdf)

Thanks!

import numpy as np

import matplotlib

from matplotlib.font_manager import FontProperties

import random

matplotlib.use(‘PDF’)

import matplotlib.pyplot as plot

small_font = FontProperties()

small_font.set_size(‘xx-small’)

ind = np.arange(20)

label = [ str® for r in ind ]

data1 = [ float(random.random()*100000000) for r in ind ]

data2 = [ float(random.random()*100000000) for r in ind ]

width = 0.25

fig = plot.figure()

ax = fig.add_subplot(111)

ax.set_title(‘Table Title’)

ax.set_xlabel(‘X Label’)

ax.barh(ind, data1, width, linewidth=0, color=‘blue’)

ax.barh(ind, data2, width, left=data1, linewidth=0, color=‘yellow’)

ax.set_yticks(ind + width/2)

ax.set_yticklabels(label, fontproperties=small_font)

ax.set_xscale(‘log’)

plot.savefig(‘matlabtest-log.pdf’)

– Christophe Pettus

Isn’t this just because zero isn’t defined in log scale? The second set of data plots fine because it doesn’t start at zero, but it isn’t obvious what to do with the first set of data. If you just want to make this work, you can set the left parameter of the first barh call to some constant; for example:

origin = 10**np.floor(np.log10(np.min(data1)))

ax.barh(ind, data1, width, left=origin, linewidth=0, color=‘blue’)

-Tony

Right, but I could have sworn that we got this fixed at some point. There is logic in the bar() function to detect logscale and handle it appropriately. But I don’t know what is not working here.

Ben Root

I think this is because the bar is going from zero to your value, so the left edge of the rectangle becomes log(0). I see this when using the ‘k’ and ‘l’ keys to interactively put a histogram on a log scale. Passing in log=True for hist fixes this. I’m sure there’s something similar that can be done for bar/barh.
G

···

On Thu, Jan 12, 2012 at 7:03 AM, Christophe Pettus <xof@…83…3912…> wrote:

I’m running into something odd in Matplotlib 1.1. In drawing a horizontal bar chart (barh), if the x-axis scale is set to log, the rectangles are not drawn and filled; I just get small ticks at the right-hand position where the rectangle should end. Interestingly, if I add a second, stacked barh to the same axes, that second set of rectangles draws fine, even though the first does not.

If I simply comment out the call setting the x axis to log, it works properly.

Any thoughts?

– Christophe Pettus

xof@…3912…


RSA® Conference 2012

Mar 27 - Feb 2

Save $400 by Jan. 27

Register now!

http://p.sf.net/sfu/rsa-sfdev2dev2


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users

D’oh! Of course, I missed that tiny little detail. Hmm, so the auto-detection would have been useless in this case because the scale of the axes was set after the fact.

Maybe the “log” kwarg should be in a more prominent location in the docstring?

Ben Root

···

On Thu, Jan 12, 2012 at 11:20 AM, Tony Yu <tsyu80@…287…> wrote:

On Thu, Jan 12, 2012 at 12:14 PM, Benjamin Root <ben.root@…1304…> wrote:

On Thu, Jan 12, 2012 at 11:04 AM, Tony Yu <tsyu80@…287…> wrote:

On Thu, Jan 12, 2012 at 11:39 AM, Christophe Pettus <xof@…3912…> wrote:

On Jan 12, 2012, at 7:38 AM, Benjamin Root wrote:

Does everything work correctly if it is vertical? In other words, use bar() and set the y-axis to log scale? An example script would be useful.

No, it doesn’t appear to work as a vertical bar chart, either.

I’ve attached a test case below. The results I get running it with the X-axis as log are:

    [http://thebuild.com/matlabtest/matlabtest-log.pdf](http://thebuild.com/matlabtest/matlabtest-log.pdf)

Commenting out the call to ax.set_xscale(‘log’) gives me:

    [http://thebuild.com/matlabtest/matlabtest.pdf](http://thebuild.com/matlabtest/matlabtest.pdf)

Thanks!

import numpy as np

import matplotlib

from matplotlib.font_manager import FontProperties

import random

matplotlib.use(‘PDF’)

import matplotlib.pyplot as plot

small_font = FontProperties()

small_font.set_size(‘xx-small’)

ind = np.arange(20)

label = [ str® for r in ind ]

data1 = [ float(random.random()*100000000) for r in ind ]

data2 = [ float(random.random()*100000000) for r in ind ]

width = 0.25

fig = plot.figure()

ax = fig.add_subplot(111)

ax.set_title(‘Table Title’)

ax.set_xlabel(‘X Label’)

ax.barh(ind, data1, width, linewidth=0, color=‘blue’)

ax.barh(ind, data2, width, left=data1, linewidth=0, color=‘yellow’)

ax.set_yticks(ind + width/2)

ax.set_yticklabels(label, fontproperties=small_font)

ax.set_xscale(‘log’)

plot.savefig(‘matlabtest-log.pdf’)

– Christophe Pettus

Isn’t this just because zero isn’t defined in log scale? The second set of data plots fine because it doesn’t start at zero, but it isn’t obvious what to do with the first set of data. If you just want to make this work, you can set the left parameter of the first barh call to some constant; for example:

origin = 10**np.floor(np.log10(np.min(data1)))

ax.barh(ind, data1, width, left=origin, linewidth=0, color=‘blue’)

-Tony

Right, but I could have sworn that we got this fixed at some point. There is logic in the bar() function to detect logscale and handle it appropriately. But I don’t know what is not working here.

Ben Root

Ahh, I didn’t know this. It looks like setting log=True in barh works.

-Tony

Moving the call to set_xscale('log') to before the calls to barh fixes the problem nicely... thank you!

···

On Jan 12, 2012, at 9:31 AM, Benjamin Root wrote:

D'oh! Of course, I missed that tiny little detail. Hmm, so the auto-detection would have been useless in this case because the scale of the axes was set after the fact.

Maybe the "log" kwarg should be in a more prominent location in the docstring?

--
-- Christophe Pettus
   xof@...3912...