matplotlib : How can I send a custom class to the plot?

Question:

I am attempting to make a simple graph such as seen here : https://matplotlib.org/stable/tutorials/introductory/pyplot.html

As you can see in the example, matplotlib wants an array of numbers such as :

import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4])
plt.ylabel('some numbers')
plt.show()

But How can I give it an array of custom classes ?

@dataclass
class TestCase:
    name: str
    time: float

Where time are the values I would like to plot

Currently I have two distinct lists : a first list with all of my custom classes and a second list where i store the time values directly. This is obviously far from ideal but I have yet to figure out how to do any better

How can I sent my custom classes ? Such as :

d1 = TestCase(name="a", 1)
d2 = TestCase(name="b", 2)
ply.plt([d1, d2])

Answers:

I guess that this is what you want, nevertheless I think that what you need is a dictionary.

In [10]: import matplotlib.pyplot as plt
    ...: from dataclasses import dataclass
    ...: 
    ...: @dataclass
    ...: class TestCase:
    ...:     name: str
    ...:     time: float
    ...: 
    ...: d1 = TestCase("a", 1)
    ...: d2 = TestCase("b", 2)
    ...: 
    ...: plt.plot(*zip(*((d.name, d.time) for d in [d1, d2])))
    ...: plt.show()

Explanation of

*zip(*((d.name, d.time) for d in [d1, d2]))
  1. ((d.name, d.time) for d in [d1, d2])
    we unpack the contents of each of the dataclasses into an iterator that yields a sequence of tuples,
  2. zip(*((d.name, d.time) for d in [d1, d2]))
    we transpose the seq. of tuples (name, time) obtaining an iterator that yields a sequence of names and a sequence of times,
  3. finally using the unpack operator (unary *) we consume and unpack said iterator.

Eventually, what is executed is like

plt.plot(seq_of_names, seq_of_times)

The OP does not like the names on the xticks?

plt.plot([d.time for d in list_of_ds])

I may be wrong but a more significant rendition, especially if you are dealing with thousands of events, could be

plt.scatter(*zip(*((1,d.time) for d in [d1, d2])), alpha=0.4)
Answered By: gboffi
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.