Skip to content

Commit

Permalink
feat(graph): Add median aggregate function (kalkih#521)
Browse files Browse the repository at this point in the history
* Add median aggregate function

* fix(graph): `_median` should return the state

Co-authored-by: Jérôme Wiedemann <[email protected]>
  • Loading branch information
2 people authored and jlsjonas committed Jan 22, 2022
1 parent 64997db commit 57219bd
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 2 deletions.
8 changes: 8 additions & 0 deletions .devcontainer/configuration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,11 @@ sensor:
unit_of_measurement: "%"
value_template: "{{ state_attr('weather.home', 'humidity') }}"
device_class: humidity
- platform: random
name: random0_100
minimum: 0
maximum: 100
- platform: random
name: random_big
minimum: 12309812
maximum: 22309812
19 changes: 18 additions & 1 deletion .devcontainer/ui-lovelace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,21 @@ views:
- sensor.pressure
show:
extrema: true
# decimals: 10
- type: custom:mini-graph-card
hours_to_show: 1
points_per_hour: 60
entities:
- entity: sensor.random0_100
name: Random 0 - 100
- type: custom:mini-graph-card
hours_to_show: 1
points_per_hour: 20
lower_bound: 0
upper_bound: 100
# agregate_fun: median
entities:
- entity: sensor.random0_100
name: Random MEDIAN
aggregate_func: median
- entity: sensor.random0_100
name: Random AVG
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ properties of the Entity object detailed in the following table (as per `sensor.
| name | string | | Set a custom display name, defaults to entity's friendly_name.
| color | string | | Set a custom color, overrides all other color options including thresholds.
| unit | string | | Set a custom unit of measurement, overrides `unit` set in base config.
| aggregate_func | string | | Override for aggregate function used to calculate point on the graph, `avg`, `min`, `max`, `first`, `last`, `sum`.
| aggregate_func | string | | Override for aggregate function used to calculate point on the graph, `avg`, `median`, `min`, `max`, `first`, `last`, `sum`.
| show_state | boolean | | Display the current state.
| show_indicator | boolean | | Display a color indicator next to the state, (only when more than two states are visible).
| show_graph | boolean | | Set to false to completely hide the entity in the graph.
Expand Down Expand Up @@ -194,6 +194,7 @@ These buckets are converted later to single point/bar on the graph. Aggregate fu
| Name | Since | Description |
|------|:-------:|-------------|
| `avg` | v0.8.0 | Average
| `median` | NEXT_VERSION | Median
| `min` | v0.8.0 | Minimum - lowest value
| `max` | v0.8.0 | Maximum - largest value
| `first` | v0.9.0 |
Expand Down
9 changes: 9 additions & 0 deletions src/graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export default class Graph {
constructor(width, height, margin, hours = 24, points = 1, aggregateFuncName = 'avg', groupBy = 'interval', smoothing = true, logarithmic = false) {
const aggregateFuncMap = {
avg: this._average,
median: this._median,
max: this._maximum,
min: this._minimum,
first: this._first,
Expand Down Expand Up @@ -201,6 +202,14 @@ export default class Graph {
return items.reduce((sum, entry) => (sum + parseFloat(entry.state)), 0) / items.length;
}

_median(items) {
const itemsDup = [...items].sort((a, b) => parseFloat(a) - parseFloat(b));
const mid = Math.floor((itemsDup.length - 1) / 2);
if (itemsDup.length % 2 === 1)
return parseFloat(itemsDup[mid].state);
return (parseFloat(itemsDup[mid].state) + parseFloat(itemsDup[mid + 1].state)) / 2;
}

_maximum(items) {
return Math.max(...items.map(item => item.state));
}
Expand Down

0 comments on commit 57219bd

Please sign in to comment.