Banillie
Banillie

Reputation: 69

Python matplotlib - None values in series of datetime values

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

Answers (2)

Max
Max

Reputation: 4045

Since your are plotting them as a scatter plot, the order is not crucial. You could index the ndarrays 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]

result

Upvotes: 1

Antonio Ragagnin
Antonio Ragagnin

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

Related Questions