Reputation: 69
I am trying to plot a series of dates. Due to an incomplete data set the series have some None values, which cause an error.
This post deals with a similar issue successfully Python matplotlib - errorbar None values in series
But I have not been able to apply it to a list of datetime.date values.
My code is
import matplotlib.pyplot as plt
import datetime
import numpy as np
fig, ax1 = plt.subplots()
keys = ["a", "b", "c", "d"]
series_one = np.array(
[
datetime.date(2020, 11, 13),
datetime.date(2021, 2, 28),
datetime.date(2021, 3, 31),
datetime.date(2021, 4, 30),
]
)
series_two = np.array(
[
datetime.date(2020, 11, 13),
datetime.date(2021, 2, 28),
datetime.date(2021, 3, 31),
None,
]
)
series_three = np.array(
[
datetime.date(2020, 11, 13),
None,
datetime.date(2021, 3, 31),
datetime.date(2020, 2, 1),
]
)
ax1.scatter(series_one, keys)
ax1.scatter(series_two, keys)
ax1.scatter(series_three, keys)
The error message:
when using NoneType
AttributeError: 'NoneType' object has no attribute 'toordinal
when using float("NaN") istead of None.
AttributeError: 'float' object has no attribute 'toordinal'
Upvotes: 0
Views: 320
Reputation: 4045
Since your are plotting them as a scatter plot, the order is not crucial. You could index the ndarray
s for non-zero elements:
import matplotlib.pyplot as plt
import datetime
import numpy as np
series_one = np.array(
[
datetime.date(2020, 11, 13),
datetime.date(2021, 2, 28),
None,
datetime.date(2021, 4, 30),
]
)
idx = series_one.nonzero()[0].tolist()
plt.scatter(series_one[idx], np.array(keys)[idx])
Since this is a feature from numpy, you need to convert the list keys
to an ndarray
before slicing: np.array(keys)[idx]
Upvotes: 1
Reputation: 2327
The core problem here is that you are passing heterogeneous list of data: datetime
objects and None
.
It is ture that the same problem happens in the question that you linked. That problem can be solved with float('nan')
because float('nan')
is a floating point element thus making all elements in the list of the same kind.
I am sorry but I think you do ned to remove the None by hand with an helper function as
def do_mask(x,y):
mask = None
mask = ~(x == None)
return np.array(x)[mask], np.array(y)[mask]
Use it as follows
import matplotlib.pyplot as plt
import datetime
import numpy as np
fig, ax1 = plt.subplots()
keys = ["a", "b", "c", "d"]
series_one = np.array(
[
datetime.date(2020, 11, 13),
datetime.date(2021, 2, 28),
datetime.date(2021, 3, 31),
datetime.date(2021, 4, 30),
]
)
series_two = np.array(
[
datetime.date(2020, 11, 13),
datetime.date(2021, 2, 28),
datetime.date(2021, 3, 31),
None
]
)
series_three = np.array(
[
datetime.date(2020, 11, 13),
None,
datetime.date(2021, 3, 31),
datetime.date(2021, 3, 31),
]
)
ax1.scatter(*do_mask(series_one, keys))
ax1.scatter(*do_mask(series_two, keys))
ax1.scatter(*do_mask(series_three, keys))
Upvotes: 1