Replace quantiles by percentile characteristic for statistics component (#81027)

* Remove quantiles characteristic

* Add percentile characteristic
This commit is contained in:
Thomas Dietrich 2022-11-14 09:23:02 +01:00 committed by GitHub
parent 727dcd6df6
commit a0b0e4088c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 71 additions and 36 deletions

View file

@ -78,7 +78,7 @@ STAT_DISTANCE_ABSOLUTE = "distance_absolute"
STAT_MEAN = "mean"
STAT_MEDIAN = "median"
STAT_NOISINESS = "noisiness"
STAT_QUANTILES = "quantiles"
STAT_PERCENTILE = "percentile"
STAT_STANDARD_DEVIATION = "standard_deviation"
STAT_SUM = "sum"
STAT_SUM_DIFFERENCES = "sum_differences"
@ -107,7 +107,7 @@ STATS_NUMERIC_SUPPORT = {
STAT_MEAN,
STAT_MEDIAN,
STAT_NOISINESS,
STAT_QUANTILES,
STAT_PERCENTILE,
STAT_STANDARD_DEVIATION,
STAT_SUM,
STAT_SUM_DIFFERENCES,
@ -135,7 +135,6 @@ STATS_NOT_A_NUMBER = {
STAT_DATETIME_OLDEST,
STAT_DATETIME_VALUE_MAX,
STAT_DATETIME_VALUE_MIN,
STAT_QUANTILES,
}
STATS_DATETIME = {
@ -157,6 +156,7 @@ STAT_NUMERIC_RETAIN_UNIT = {
STAT_MEAN,
STAT_MEDIAN,
STAT_NOISINESS,
STAT_PERCENTILE,
STAT_STANDARD_DEVIATION,
STAT_SUM,
STAT_SUM_DIFFERENCES,
@ -177,13 +177,10 @@ CONF_STATE_CHARACTERISTIC = "state_characteristic"
CONF_SAMPLES_MAX_BUFFER_SIZE = "sampling_size"
CONF_MAX_AGE = "max_age"
CONF_PRECISION = "precision"
CONF_QUANTILE_INTERVALS = "quantile_intervals"
CONF_QUANTILE_METHOD = "quantile_method"
CONF_PERCENTILE = "percentile"
DEFAULT_NAME = "Stats"
DEFAULT_PRECISION = 2
DEFAULT_QUANTILE_INTERVALS = 4
DEFAULT_QUANTILE_METHOD = "exclusive"
ICON = "mdi:calculator"
@ -248,11 +245,8 @@ _PLATFORM_SCHEMA_BASE = PLATFORM_SCHEMA.extend(
vol.Optional(CONF_SAMPLES_MAX_BUFFER_SIZE): vol.Coerce(int),
vol.Optional(CONF_MAX_AGE): cv.time_period,
vol.Optional(CONF_PRECISION, default=DEFAULT_PRECISION): vol.Coerce(int),
vol.Optional(
CONF_QUANTILE_INTERVALS, default=DEFAULT_QUANTILE_INTERVALS
): vol.All(vol.Coerce(int), vol.Range(min=2)),
vol.Optional(CONF_QUANTILE_METHOD, default=DEFAULT_QUANTILE_METHOD): vol.In(
["exclusive", "inclusive"]
vol.Optional(CONF_PERCENTILE, default=50): vol.All(
vol.Coerce(int), vol.Range(min=1, max=99)
),
}
)
@ -283,8 +277,7 @@ async def async_setup_platform(
samples_max_buffer_size=config[CONF_SAMPLES_MAX_BUFFER_SIZE],
samples_max_age=config.get(CONF_MAX_AGE),
precision=config[CONF_PRECISION],
quantile_intervals=config[CONF_QUANTILE_INTERVALS],
quantile_method=config[CONF_QUANTILE_METHOD],
percentile=config[CONF_PERCENTILE],
)
],
update_before_add=True,
@ -303,8 +296,7 @@ class StatisticsSensor(SensorEntity):
samples_max_buffer_size: int,
samples_max_age: timedelta | None,
precision: int,
quantile_intervals: int,
quantile_method: Literal["exclusive", "inclusive"],
percentile: int,
) -> None:
"""Initialize the Statistics sensor."""
self._attr_icon: str = ICON
@ -319,8 +311,7 @@ class StatisticsSensor(SensorEntity):
self._samples_max_buffer_size: int = samples_max_buffer_size
self._samples_max_age: timedelta | None = samples_max_age
self._precision: int = precision
self._quantile_intervals: int = quantile_intervals
self._quantile_method: Literal["exclusive", "inclusive"] = quantile_method
self._percentile: int = percentile
self._value: StateType | datetime = None
self._unit_of_measurement: str | None = None
self._available: bool = False
@ -700,18 +691,10 @@ class StatisticsSensor(SensorEntity):
return cast(float, self._stat_sum_differences()) / (len(self.states) - 1)
return None
def _stat_quantiles(self) -> StateType:
if len(self.states) > self._quantile_intervals:
return str(
[
round(quantile, self._precision)
for quantile in statistics.quantiles(
self.states,
n=self._quantile_intervals,
method=self._quantile_method,
)
]
)
def _stat_percentile(self) -> StateType:
if len(self.states) >= 2:
percentiles = statistics.quantiles(self.states, n=100, method="exclusive")
return percentiles[self._percentile - 1]
return None
def _stat_standard_deviation(self) -> StateType: