0

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])
  • What would you like your "classes plot" to be like? What will be on the X axis and on the Y axis? – Yulia V Oct 13 '22 at 13:54
  • on the X axis I have the individual tests and on the y axis I have the time values. So if I have 3000 tests I would see them all individually on the x axis and the y axis would represent the values ranging from the minimum to maximum – Matthieu Raynaud de Fitte Oct 13 '22 at 14:02
  • so far I am achieving it but with a secondary list of time values independent from the object values. It works as I get to display the values I want to see but it's not ideal as I need to be cautious to always edit both lists at once – Matthieu Raynaud de Fitte Oct 13 '22 at 14:04
  • @MatthieuRaynauddeFitte - looks like you need text labels on X axis. This is how you can achieve it --> https://stackoverflow.com/questions/3100985/plot-with-custom-text-for-x-axis-points Could you give it a try and let us know how you are getting on? – Yulia V Oct 13 '22 at 14:09
  • I already use text labels ( `plt.ylabel("time in seconds")` ) more precisely but this is only to labels where as what I would like to have is to be able to read from the TestCase array directly. Right now I have two separate arrays. A float array and a TestCase array. I have those two separate arrays as I do not know how to get the plot() method to take my TestCase array. So I give is the secondary array witch possesses all of the time values. But having those two separate yet linked arrays is quite the pain and is not ideal. Hence I would like to only have one array of TestCase – Matthieu Raynaud de Fitte Oct 13 '22 at 14:13
  • 1
    A dictionary — that now guarantees that the insertion order is respected — could be a better data structure. ፨ Overall, to me it looks like an [X-Y problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – gboffi Oct 15 '22 at 10:08

1 Answers1

3

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)
gboffi
  • 22,939
  • 8
  • 54
  • 85
  • thank you for your answer but I do not wish to represent the names at all, that is an extra piece of data the rest of the program uses but is not needed for the plotting. I apologize if the question is not clear enough – Matthieu Raynaud de Fitte Oct 13 '22 at 14:41
  • on the Y axis I have the time in seconds and on the x axis I have all of the individual tests. You did however provide me with the answer I was seeking for : plt.plot([test.time for test in tests]). I was hoping to give the values directly to the plot method but it made me miss something obvious. Could you please edit your answer that I may accept it ? – Matthieu Raynaud de Fitte Oct 13 '22 at 14:45