0

I'm trying to plot some timelines including NaN's with pyplot (see sample code). The problem is, that when there's a NaN, pyplot doesn't draw a line between the points before and after the NaN. Is there any solution to change this behaviour? I don't want to fill in any computed data points instead of the NaN. Deleting the NaN is not an option either, because that would result in the x- and y-lists having different lengths.

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
y = [1, 2, 5, 4, 7, "nan", 4, 2, 5, 4, 4, 1]

plt.show(plt.plot(x, y, 'o-', linewidth = 0.5))

Thanks a lot, Julian

3
  • 1
    Are your values really "nan" i.e a string? Or are they actually NaN? Commented Jan 16, 2018 at 16:24
  • @ViníciusAguiar: The approach in the other thread is to fill the NaN gap with computed data points. That's what I don't want to do. Commented Jan 16, 2018 at 19:50
  • @DavidG: currently, it's really "nan", but I could change that to NaN easily if it helps to find an easy solution. Commented Jan 16, 2018 at 19:51

2 Answers 2

1

Assuming you're actually talking about np.nan, I frequently address this problem by:

x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
y = np.array([1, 2, 5, 4, 7, "nan", 4, 2, 5, 4, 4, 1], dtype=np.float64)

goods = ~np.isnan(y)

line = plt.plot(x[goods], y[goods], 'o-', linewidth = 0.5)

This way your x and y variables are unchanged, but the plot doesn't have gaps. Note here that I've:

  • initalized x and y as arrays at the outset so that they can be indexed by the boolean array goods
  • forced y to be a np.float64 array (so that 'nan' becomes a np.nan).

Sidenote

If you really are talking about the string 'nan' (or some other string you want to exclude), you could do something like:

y = np.array([1, 2, 5, 4, 7, "nan", 4, 2, 5, 4, 4, 1])
goods = (y != "nan")

Note that in this case, I haven't forced y to be float64, and so it ends up being a |S21. However, matplotlib converts this to float64 (take a look at line[0].get_xydata()) before plotting so in general it's probably simplest to apply the first approach. Otherwise, matplotlib might throw errors if there are other strings in y that can't be converted to float64.

Sign up to request clarification or add additional context in comments.

2 Comments

I'll try that tomorrow, thanks.
Worked for me, thanks for the solution!
0

I know you said you prefer to not have to remove the "nan". However, I know of no other way to get the line to connect (without interpolation, or filling the data somehow). So, I suspect the easiest options might be to remove the "nan" from y and the corresponding index in x.

>>> del x[y.index("nan")]
>>> x
[1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12]

>>> y.remove("nan")
>>> y
[1, 2, 5, 4, 7, 4, 2, 5, 4, 4, 1]

1 Comment

That unfortunately doesn't work for me, because I use the x list for different plots with different y lists.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.