简体   繁体   中英

Zigzag or wavy lines in matplotlib

Is there an easy way to draw a zigzag or wavy line in matplotlib?

I'm aware of the different line styles ( http://matplotlib.org/examples/lines_bars_and_markers/line_styles_reference.html ), and I'm of course aware that instead of plotting

plt.figure(); plt.plot(n.linspace(0.7,1.42,100),[0.7]*100)

I could plot

plt.figure(); plt.plot(n.linspace(0.7,1.42,100),[0.69,0.71]*50)

for a zigzag-line, but I was wondering whether there was a more straightforward way?

Yes there is, but it comes with a little bit of fallout. The easiest way is to use the xkcd mode in matplotlib.

import numpy as np
import matplotlib.pyplot as plt

plt.xkcd()
plt.figure()
plt.plot(np.linspace(0.7,1.42,100),[0.7]*100)
plt.show()

Which gives you the following: 在此处输入图片说明

If you take a look at the code used to achieve this you will find that the xkcd function makes some changes to the rcParams dictionary. Most notably the entry rcParams['path.sketch'] = (scale, length, randomness) which is a path effect that is able to simulate a hand drawn look. The default parameters used by xkcd style are:

# explanation from the docstring of the xkcd function
scale = 1  # amplitude of the wiggle
length = 100  # length of the wiggle along the line
randomness = 2  # scale factor for shrinking and expanding the length

You can change the entries in the rcParams dictionary if you import it from the matplotlib package. In the following example I increased the randomness value from 2 to 100 :

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rcParams

rcParams['path.sketch'] = (1, 100, 100)
plt.plot(np.linspace(0.7,1.42,100),[0.7]*100)
plt.show()

Which will result in the following plot:

在此处输入图片说明

As you can see, more jiggling and the font used for the ticks is still 'normal'. However, the style is also used to draw the axes and so far I have not found a way around that. Two workarounds could be:

  1. Work without drawn borders/ spines.
  2. Plot spines and line independently (hard and annoying to automize).
  3. Dig through the documentation of matplotlib and path styles and find out if there is a way to set path styles only for a subset of drawn lines.

Option 1 can be achieved like this:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rcParams

rcParams['path.sketch'] = (10, 10, 100)
fig = plt.plot(np.linspace(0.7,1.42,100),[0.7]*100)

for pos, spine in fig[0].axes.spines.items():
    spine.set_visible(False)
plt.show()

在此处输入图片说明

Which, in my opinion look quite ok. borders around plots are highly overrated anyways.

Edit: Less Chaos

To get an evenly waved line, set the randomness parameter to 1 and pick small values for amplitude and length:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rcParams

rcParams['path.sketch'] = (3, 10, 1)
fig = plt.plot(np.linspace(0.7,1.42,100),[0.7]*100)

for pos, spine in fig[0].axes.spines.items():
    spine.set_visible(False)
plt.show()

在此处输入图片说明

Bonus image: More Chaos

rcParams['path.sketch'] = (100, 1, 100)

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM