14

The data I am visualising only makes sense if it is whole numbers.

I.e. 0.2 of a record doesn't make sense in terms of the context of the information I am analysing.

How do I force matplotlib to only use whole numbers on the Y axis. I.e. 1, 100, 5 etc? not 0.1, 0.2 etc

for a in account_list:
    f = plt.figure()
    f.set_figheight(20)
    f.set_figwidth(20)
    f.sharex = True
    f.sharey=True

    left  = 0.125  # the left side of the subplots of the figure
    right = 0.9    # the right side of the subplots of the figure
    bottom = 0.1   # the bottom of the subplots of the figure
    top = 0.9      # the top of the subplots of the figure
    wspace = 0.2   # the amount of width reserved for blank space between subplots
    hspace = .8  # the amount of height reserved for white space between subplots
    subplots_adjust(left=left, right=right, bottom=bottom, top=top, wspace=wspace, hspace=hspace)

    count = 1
    for h in headings:
        sorted_data[sorted_data.account == a].ix[0:,['month_date',h]].plot(ax=f.add_subplot(7,3,count),legend=True,subplots=True,x='month_date',y=h)

        #set bottom Y axis limit to 0 and change number format to 1 dec place.
        axis_data = f.gca()
        axis_data.set_ylim(bottom=0.)
        from matplotlib.ticker import FormatStrFormatter
        axis_data.yaxis.set_major_formatter(FormatStrFormatter('%.0f'))

        #This was meant to set Y axis to integer???
        y_formatter = matplotlib.ticker.ScalarFormatter(useOffset=False)
        axis_data.yaxis.set_major_formatter(y_formatter)

        import matplotlib.patches as mpatches

        legend_name = mpatches.Patch(color='none', label=h)
        plt.xlabel("")
        ppl.legend(handles=[legend_name],bbox_to_anchor=(0.,1.2,1.0,.10), loc="center",ncol=2, mode="expand", borderaxespad=0.)
        count = count + 1
        savefig(a + '.png', bbox_inches='tight')
Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
yoshiserry
  • 20,175
  • 35
  • 77
  • 104

4 Answers4

18

The most flexible way is to specify integer=True to the default tick locator (MaxNLocator) do something similar to this:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

fig, ax = plt.subplots()

# Be sure to only pick integer tick locations.
for axis in [ax.xaxis, ax.yaxis]:
    axis.set_major_locator(ticker.MaxNLocator(integer=True))

# Plot anything (note the non-integer min-max values)...
x = np.linspace(-0.1, np.pi, 100)
ax.plot(0.5 * x, 22.8 * np.cos(3 * x), color='black')

# Just for appearance's sake
ax.margins(0.05)
ax.axis('tight')
fig.tight_layout()

plt.show()

enter image description here

Alternatively, you can manually set the tick locations/labels as Marcin and Joel suggest (or use a MultipleLocator). The downside to this is that you need to work out what tick positions make sense, rather than having matplotlib pick a reasonable integer tick interval based on the axis limits.

Joe Kington
  • 275,208
  • 71
  • 604
  • 463
  • Thanks @Joe Kington -- Can you help me I feel I am using it wrong: I get the error : axis_data.set_major_locator(ticker.MaxNLocator(integer=True)) 'AxesSubplot' object has no attribute 'set_major_locator'. Is this because I am trying to set the Y axis to integers for SUBPLOTS? – yoshiserry Dec 16 '14 at 03:15
  • @yoshiserry - I'm guessing that you're trying to call `ax.set_major_locator` instead of `ax.yaxis.set_major_locator`. The tick locator is an attribute of the `Axis` (i.e. x/y axis), not the `Axes` (i.e. the plot). Try `axis_data.yaxis.set_major_locator` (or `xaxis`, depending). – Joe Kington Dec 16 '14 at 03:17
11

Another way of forcing integer ticks is to use pyplot.locator_params.

Using almost the same example as in the accepted answer:

import numpy as np
import matplotlib.pyplot as plt

# Plot anything (note the non-integer min-max values)...
x = np.linspace(-0.1, np.pi, 100)
plt.plot(0.5 * x, 22.8 * np.cos(3 * x), color='black')

# use axis={'both', 'x', 'y'} to choose axis
plt.locator_params(axis="both", integer=True, tight=True)

# Just for appearance's sake
plt.margins(0.05)
plt.tight_layout()

plt.show()

plot

Sergey
  • 1,166
  • 14
  • 27
7

If it's just the yaxis you want to change, an easy way is to determine which ticks you want:

tickpos = [0,1,4,6]

py.yticks(tickpos,tickpos)

will put ticks at 0, 1, 4, and 6. More generally

py.yticks([0,1,2,3], ['zero', 1, 'two', 3.0])

will put the label of the second list at the location in the first list. If the label is going to be the yvalue, it's a good idea to use the py.yticks(tickpos,tickpos) version just to make sure that whenever you change the locations of the ticks, the labels get the same change.

More generally though, Kington's answer will let you tell pylab just integers for the y axis, but let it choose where the ticks go.

Joel
  • 22,598
  • 6
  • 69
  • 93
1

You can modify tick labels/numbers as follows. This is example only, as you have not provided any code that you have, so not sure if it applys to you or not.

import matplotlib.pyplot as plt

fig, ax = plt.subplots()

fig.canvas.draw()

# just the original labels/numbers and modify them, e.g. multiply by 100
# and define new format for them.
labels = ["{:0.0f}".format(float(item.get_text())*100) 
                for item in ax.get_xticklabels()]


ax.set_xticklabels(labels)

plt.show()

Without modification of x axis:

enter image description here

WIth the modification:

enter image description here

Marcin
  • 215,873
  • 14
  • 235
  • 294