89

It seems that the set_xticks is not working in log scale:

from matplotlib import pyplot as plt
fig1, ax1 = plt.subplots()
ax1.plot([10, 100, 1000], [1,2,3])
ax1.set_xscale('log')
ax1.set_xticks([20, 200, 500])
plt.show()

is it possible?

MERose
  • 4,048
  • 7
  • 53
  • 79
Ruggero Turra
  • 16,929
  • 16
  • 85
  • 141

6 Answers6

108
import matplotlib
from matplotlib import pyplot as plt
fig1, ax1 = plt.subplots()
ax1.plot([10, 100, 1000], [1,2,3])
ax1.set_xscale('log')
ax1.set_xticks([20, 200, 500])
ax1.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter())

or

ax1.get_xaxis().get_major_formatter().labelOnlyBase = False
plt.show()

resulting plot

asmeurer
  • 86,894
  • 26
  • 169
  • 240
tacaswell
  • 84,579
  • 22
  • 210
  • 199
  • 14
    Hi, Could you add some explanation as well as a plot of what this outcome looks like? – Joel Jan 07 '16 at 01:12
  • the second option will keep the logarithmic notation in the ticks, ie 20 is going to be 10^1.3 – grasshopper Sep 01 '16 at 17:07
  • This is fine if the labels match their numeric value, but what if you want them to be some other strings? – asmeurer Mar 20 '17 at 21:08
  • I am a big fan of http://matplotlib.org/api/ticker_api.html?highlight=funcformatter#matplotlib.ticker.FuncFormatter which lets you wring a function mapping value -> string. Else use http://matplotlib.org/api/ticker_api.html?highlight=funcformatter#matplotlib.ticker.FixedFormatter + http://matplotlib.org/api/ticker_api.html?highlight=funcformatter#matplotlib.ticker.FixedLocator – tacaswell Mar 20 '17 at 22:47
  • 3
    @tacaswell: The exponential notation `3x10^1` etc. still remains! How do I remove it ? – Srivatsan Jan 16 '18 at 02:21
  • You probably have to turn off the minor formatter as well. – tacaswell Jan 17 '18 at 18:08
  • @tacaswell The 2nd is exactly what I need, but it does not work. I used `set_xticks` to designate what I need, but only the base-conforming ones were displayed, even though the others became 'major' ticks. – physkets Apr 14 '20 at 08:49
23

I'm going to add a few plots and show how to remove the minor ticks:

The OP:

from matplotlib import pyplot as plt

fig1, ax1 = plt.subplots()
ax1.plot([10, 100, 1000], [1,2,3])
ax1.set_xscale('log')
ax1.set_xticks([20, 300, 500])
plt.show()

enter image description here

To add some specific ticks, as tcaswell pointed out, you can use matplotlib.ticker.ScalarFormatter:

from matplotlib import pyplot as plt
import matplotlib.ticker

fig1, ax1 = plt.subplots()
ax1.plot([10, 100, 1000], [1,2,3])
ax1.set_xscale('log')
ax1.set_xticks([20, 300, 500])
ax1.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter())
plt.show()

enter image description here

To remove the minor ticks, you can use matplotlib.rcParams['xtick.minor.size']:

from matplotlib import pyplot as plt
import matplotlib.ticker

matplotlib.rcParams['xtick.minor.size'] = 0
matplotlib.rcParams['xtick.minor.width'] = 0

fig1, ax1 = plt.subplots()
ax1.plot([10, 100, 1000], [1,2,3])
ax1.set_xscale('log')
ax1.set_xticks([20, 300, 500])
ax1.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter())

plt.show()

enter image description here

You could use instead ax1.get_xaxis().set_tick_params, it has the same effect (but only modifies the current axis, not all future figures unlike matplotlib.rcParams):

from matplotlib import pyplot as plt
import matplotlib.ticker

fig1, ax1 = plt.subplots()
ax1.plot([10, 100, 1000], [1,2,3])
ax1.set_xscale('log')
ax1.set_xticks([20, 300, 500])
ax1.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter())

ax1.get_xaxis().set_tick_params(which='minor', size=0)
ax1.get_xaxis().set_tick_params(which='minor', width=0) 

plt.show()

enter image description here

Community
  • 1
  • 1
Franck Dernoncourt
  • 77,520
  • 72
  • 342
  • 501
5

Would be better to use np.geomspace as xticks

ax = sns.histplot(arr, log_scale=True)
ax.xaxis.set_major_formatter(matplotlib.ticker.ScalarFormatter())
ax.set_xticks( np.geomspace(1, 1500 ,15).round() )

enter image description here

Mithril
  • 12,947
  • 18
  • 102
  • 153
5
from matplotlib.ticker import ScalarFormatter, NullFormatter
for axis in [ax.xaxis]:
    axis.set_major_formatter(ScalarFormatter())
    axis.set_minor_formatter(NullFormatter())

This removes the exponential notation

PyariBilli
  • 501
  • 1
  • 7
  • 17
0

To make a semi-log plot with x-scale logarithmic, there are two options:

import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(x,y)
ax.set_xscale('log')

or

import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.semilogx(x,y)

If you do not need to set the xticks, this two are both fine.

If you do need to set the xticks, the second one would be better.

Similarly,

ax.loglog(x,y)

is better than

ax.plot(x,y)
ax.set_xscale('log')
ax.set_yscale('log')

when setting ticks is a must;

ax.semilogy(x,y)

is better than

ax.plot(x,y)
ax.set_yscale('log')

when setting ticks is needed.

-1
from matplotlib import pyplot as plt

fig1, ax1 = plt.subplots()
ax1.plot([10, 100, 1000], [1,2,3])
ax1.set_xscale('log')
ax1.set_xticks([20, 200, 500])
plt.xscale("log")       # <<< !
plt.show()

enter image description here

JeeyCi
  • 354
  • 2
  • 9