mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[ML] Extend population preview chart to show actual and typical value (#67569)
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
573409b9f0
commit
2266dd969e
2 changed files with 51 additions and 10 deletions
|
@ -25,6 +25,7 @@ import {
|
|||
getTickValues,
|
||||
numTicksForDateFormat,
|
||||
removeLabelOverlap,
|
||||
chartExtendedLimits,
|
||||
} from '../../util/chart_utils';
|
||||
import { LoadingIndicator } from '../../components/loading_indicator/loading_indicator';
|
||||
import { getTimeBucketsFromCache } from '../../util/time_buckets';
|
||||
|
@ -98,7 +99,7 @@ export class ExplorerChartDistribution extends React.Component {
|
|||
const filteredChartData = init(config);
|
||||
drawRareChart(filteredChartData);
|
||||
|
||||
function init({ chartData }) {
|
||||
function init({ chartData, functionDescription }) {
|
||||
const $el = $('.ml-explorer-chart');
|
||||
|
||||
// Clear any existing elements from the visualization,
|
||||
|
@ -137,22 +138,24 @@ export class ExplorerChartDistribution extends React.Component {
|
|||
});
|
||||
|
||||
if (chartType === CHART_TYPE.POPULATION_DISTRIBUTION) {
|
||||
const focusData = chartData
|
||||
.filter((d) => {
|
||||
return d.entity === highlight;
|
||||
})
|
||||
.map((d) => d.value);
|
||||
const focusExtent = d3.extent(focusData);
|
||||
|
||||
const focusData = chartData.filter((d) => {
|
||||
return d.entity === highlight;
|
||||
});
|
||||
// calculate the max y domain based on value, typical, and actual
|
||||
// also sets the min to be at least 0 if the series function type is `count`
|
||||
const { min: yScaleDomainMin, max: yScaleDomainMax } = chartExtendedLimits(
|
||||
focusData,
|
||||
functionDescription
|
||||
);
|
||||
// now again filter chartData to include only the data points within the domain
|
||||
chartData = chartData.filter((d) => {
|
||||
return d.value <= focusExtent[1];
|
||||
return d.value <= yScaleDomainMax;
|
||||
});
|
||||
|
||||
lineChartYScale = d3.scale
|
||||
.linear()
|
||||
.range([chartHeight, 0])
|
||||
.domain([0, focusExtent[1]])
|
||||
.domain([yScaleDomainMin < 0 ? yScaleDomainMin : 0, yScaleDomainMax])
|
||||
.nice();
|
||||
} else if (chartType === CHART_TYPE.EVENT_DISTRIBUTION) {
|
||||
// avoid overflowing the border of the highlighted area
|
||||
|
|
|
@ -65,6 +65,44 @@ export function chartLimits(data = []) {
|
|||
return limits;
|
||||
}
|
||||
|
||||
export function chartExtendedLimits(data = [], functionDescription) {
|
||||
let _min = Infinity;
|
||||
let _max = -Infinity;
|
||||
data.forEach((d) => {
|
||||
let metricValue = d.value;
|
||||
const actualValue = Array.isArray(d.actual) ? d.actual[0] : d.actual;
|
||||
const typicalValue = Array.isArray(d.typical) ? d.typical[0] : d.typical;
|
||||
|
||||
if (metricValue === null && d.anomalyScore !== undefined && d.actual !== undefined) {
|
||||
// If an anomaly coincides with a gap in the data, use the anomaly actual value.
|
||||
metricValue = actualValue;
|
||||
}
|
||||
|
||||
if (d.anomalyScore !== undefined) {
|
||||
_min = Math.min(_min, metricValue, actualValue, typicalValue);
|
||||
_max = Math.max(_max, metricValue, actualValue, typicalValue);
|
||||
} else {
|
||||
_min = Math.min(_min, metricValue);
|
||||
_max = Math.max(_max, metricValue);
|
||||
}
|
||||
});
|
||||
const limits = { max: _max, min: _min };
|
||||
|
||||
// add padding of 5% of the difference between max and min
|
||||
// if we ended up with the same value for both of them
|
||||
if (limits.max === limits.min) {
|
||||
const padding = limits.max * 0.05;
|
||||
limits.max += padding;
|
||||
limits.min -= padding;
|
||||
}
|
||||
|
||||
// makes sure the domain starts at 0 if the aggregation is by count
|
||||
// since the number should always be positive
|
||||
if (functionDescription === 'count' && limits.min < 0) {
|
||||
limits.min = 0;
|
||||
}
|
||||
return limits;
|
||||
}
|
||||
export function drawLineChartDots(data, lineChartGroup, lineChartValuesLine, radius = 1.5) {
|
||||
// We need to do this because when creating a line for a chart which has data gaps,
|
||||
// if there are single datapoints without any valid data before and after them,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue