4

I want to create some xkcd plots with a grid in the background. Like this example, but when the plt.xkcd() the grids don't appear in the plot.

from matplotlib import pyplot as plt
import numpy as np

plt.xkcd()
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
plt.xticks([])
plt.yticks([])
ax.set_ylim([-30, 10])
plt.grid()

data = np.ones(100)
data[70:] -= np.arange(30)

plt.annotate(
    'THE DAY I REALIZED\nI COULD COOK BACON\nWHENEVER I WANTED',
    xy=(70, 1), arrowprops=dict(arrowstyle='->'), xytext=(15, -10))

plt.plot(data)

plt.xlabel('time')
plt.ylabel('my overall health')

plt.show()

In the case of plots done with mplot3d the grid is "working", as can be seen in this example. Although, the grid seems to be perfect. How can I create the grids?

nicoguaro
  • 3,629
  • 1
  • 32
  • 57

3 Answers3

7

I'm expanding my comment into an answer. As DrV mentioned, the linewidth is set to zero, so we need to explicitly specified in the call to grid(). Other thing to take into account is that the grid will appear over the plot, so the zorder need to be specified. As mentioned in this post, the grid should be set with zorder=0 and the plot should have a value greater to 3 zorder=3.

So, an example without grid is

import numpy as np
import matplotlib.pyplot as plt

plt. xkcd()
x = np.linspace(0, 1)
y = np.sin(4 * np.pi * x) * np.exp(-5 * x)

plt.fill(x, y, 'r')
plt.grid(True)
plt.show()

Giving: xkcd-style plot withtout grid

An example with grid:

import numpy as np
import matplotlib.pyplot as plt

plt. xkcd()
x = np.linspace(0, 1)
y = np.sin(4 * np.pi * x) * np.exp(-5 * x)

plt.fill(x, y, 'r', zorder=3)
plt.grid(True, lw=0.5, zorder=0)
plt.show()

Giving: enter image description here

Community
  • 1
  • 1
nicoguaro
  • 3,629
  • 1
  • 32
  • 57
3

The first reason is that you have no gridlines:

In [43]: ax.xaxis.get_gridlines()
Out[43]: <a list of 0 Line2D gridline objects>

This is because you have no xticks:

In [47]: ax.get_xticks()
Out[47]: array([], dtype=float64)

This can be fixed by adding some ticks:

ax.set_xticks([20,50,80])
ax.set_yticks([-20,-10,0])

Now we should have some gridlines:

In [54]: ax.xaxis.get_gridlines()
Out[54]: <a list of 3 Line2D gridline objects>

Unfortunately, nothing can be seen. That, in turn, is because the grid width is zero:

In [56]: ax.xaxis.get_gridlines()[0].get_linewidth()
Out[56]: 0.0

We can fix that by (see below for a more general method):

ax.xaxis.grid(linewidth=1.0)
ax.yaxis.grid(linewidth=1.0)

And now you have:

enter image description here

Of course, in practice you will set the x and y ticks as you wish (and maybe switch off the tick marks themselves). After that you can simply set the grid on by:

ax.grid(True, linewidth=1)

Please not that the ticks were removed on purpose in the beginning of the example code.

DrV
  • 22,637
  • 7
  • 60
  • 72
  • The code didn't have ticks, you're right. Maybe it was a better idea to use the one in the fist hyperlink. Thanks to answer my question. – nicoguaro Jul 28 '14 at 18:27
  • I should also mention that if we want the grid to be in the background we need to explicitly say it (see this [post](http://stackoverflow.com/questions/23357798/how-to-draw-grid-lines-behind-matplotlib-bar-graph). Example: `from matplotlib import pyplot as plt import numpy as np x = np.linspace(0,10,200) plt.xkcd() plt.plot(x,np.sin(x), zorder=3); plt.grid(True, lw=1, zorder=0) plt.show()` – nicoguaro Jul 28 '14 at 21:47
1

xkcd mode changes the following 2 rcParams directly affecting gridlines:

from matplotlib import rcParams

rcParams['axes.grid']= False     # defaults to False but xkcd() makes it False
rcParams['grid.linewidth']= 0.0  # defaults to 0.8

Simply change these to what you need. If the gridlines in your chart were working just fine before, and xkcd mode broke the gridlines, setting these two values to what they were before should address the issue. No need to rework zorders and the like, unless you're doing more than just un-breaking your previously working chart.