scalanlp / breeze

Breeze is/was a numerical processing library for Scala.
https://www.scalanlp.org
Apache License 2.0
3.45k stars 692 forks source link

How to plot a Map? #805

Closed phdoerfler closed 3 years ago

phdoerfler commented 3 years ago

What happened so far

I searched for libraries to do one dimensional morphological operations on signals, re-discovered breeze, looked through the quickstart and lo and behold discovered this:

image

Awesome!

image

We're finally approaching python numpy levels of plot(whatever), excellent!

Despite being a complete Breeze newb I managed to plot some data from a Prometheus DB:

Next thing was to deal with the missing values just like Prometheus did in its graph. It was not long that I was writing my own DomainFunction implicit. Fast forward: I saw that there is an implicit for plotting Maps. Perfect, I thought, since my data looks like this:

science: IndexedSeq[Datapoint] = Vector(
  Datapoint(instant = 2021-04-04T14:00:00Z, value = "866549"),
  Datapoint(instant = 2021-04-04T15:00:00Z, value = "870944"),
  Datapoint(instant = 2021-04-04T16:00:00Z, value = "878367"),
  Datapoint(instant = 2021-04-04T17:00:00Z, value = "881706"),
  Datapoint(instant = 2021-04-04T18:00:00Z, value = "885156"),
  Datapoint(instant = 2021-04-04T19:00:00Z, value = "892424"),

or, a few maps later:

mappy: Map[Int, Double] = HashMap(
  449463 -> 1811260.0,
  449388 -> 1330179.0,
  449356 -> 1088255.0,
  449369 -> 1209736.0,
  449502 -> 2157084.0,

But how would I feed it to plot? After all, it takes an X and a Y and that Map already has both of those. Glancing at the source I wasn't any wiser:

implicit def mapIsDomainFunction[T, K, V](implicit ev: T <:< collection.Map[K, V]): DomainFunction[T, K, V] = {
  new DomainFunction[T, K, V] {
    def domain(t: T): IndexedSeq[K] = t.keySet.toIndexedSeq
    def apply(t: T, k: K): V = {
      t(k)
    }
  }
}

It knows what the domain, the x axis, is and it knows how to get the values, the y axis, based on the domain. Right?

So why can't I just plot(mappy)? Since there's already an implicit for Map, is there any code that uses it? I searched the source on Github to no avail. fwiw out of curiosity:

p += plot(mappy, mappy)

did at least compile and give me:

image

A straight line. Not overly surprising.

So: How to plot a Map? I might be persuaded into filing a PR for adding this to the quickstart once I know how to do it, so the next person (AKA me in a few months) won't have to scratch their head.

phdoerfler commented 3 years ago

On a side note: I don't suppose a SparseVector is what I'm looking for to best model the missing values, is it?

phdoerfler commented 3 years ago

On another side note: how does breeze know in which order to plot the map’s keys? After all it’s not an OrderedMap and I think my code compiled even without having an implicit Ordering for Instant.

phdoerfler commented 3 years ago

Turns out, if I clone the repo and remove the Map DomainFunction implicit breeze still compiles. It would seem the implicit is unused and thus my search for code using relying on it was deemed fruitless from the very beginning.

phdoerfler commented 3 years ago

Alright, I think I figured it out. It didn't help that I'm not an English native speaker. Once I learned what function domain translates to the veil of confusion started to lift itself.