Skip to content

Commit 0785fb7

Browse files
committed
[ML] Add callout for legacy feature influence data.
1 parent de33e97 commit 0785fb7

File tree

3 files changed

+48
-4
lines changed

3 files changed

+48
-4
lines changed

x-pack/plugins/ml/common/types/data_frame_analytics.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ export type DataFrameAnalyticsId = string;
1919
export interface OutlierAnalysis {
2020
[key: string]: {};
2121

22-
outlier_detection: {};
22+
outlier_detection: {
23+
compute_feature_influence?: boolean;
24+
};
2325
}
2426

2527
interface Regression {

x-pack/plugins/ml/common/util/analytics_utils.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,19 @@ import {
1313
import { ANALYSIS_CONFIG_TYPE } from '../../common/constants/data_frame_analytics';
1414

1515
export const isOutlierAnalysis = (arg: any): arg is OutlierAnalysis => {
16+
if (typeof arg !== 'object' || arg === null) return false;
1617
const keys = Object.keys(arg);
1718
return keys.length === 1 && keys[0] === ANALYSIS_CONFIG_TYPE.OUTLIER_DETECTION;
1819
};
1920

2021
export const isRegressionAnalysis = (arg: any): arg is RegressionAnalysis => {
22+
if (typeof arg !== 'object' || arg === null) return false;
2123
const keys = Object.keys(arg);
2224
return keys.length === 1 && keys[0] === ANALYSIS_CONFIG_TYPE.REGRESSION;
2325
};
2426

2527
export const isClassificationAnalysis = (arg: any): arg is ClassificationAnalysis => {
28+
if (typeof arg !== 'object' || arg === null) return false;
2629
const keys = Object.keys(arg);
2730
return keys.length === 1 && keys[0] === ANALYSIS_CONFIG_TYPE.CLASSIFICATION;
2831
};

x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66

77
import React, { useState, FC } from 'react';
88

9-
import { EuiSpacer, EuiText } from '@elastic/eui';
9+
import { EuiCallOut, EuiSpacer, EuiText } from '@elastic/eui';
10+
11+
import { i18n } from '@kbn/i18n';
1012

1113
import {
1214
useColorRange,
@@ -15,7 +17,8 @@ import {
1517
} from '../../../../../components/color_range_legend';
1618
import { SavedSearchQuery } from '../../../../../contexts/ml';
1719

18-
import { defaultSearchQuery, useResultsViewConfig } from '../../../../common';
20+
import { defaultSearchQuery, isOutlierAnalysis, useResultsViewConfig } from '../../../../common';
21+
import { FEATURE_INFLUENCE } from '../../../../common/constants';
1922

2023
import { ExpandableSectionAnalytics, ExpandableSectionResults } from '../expandable_section';
2124
import { ExplorationQueryBar } from '../exploration_query_bar';
@@ -39,6 +42,24 @@ export const OutlierExploration: FC<ExplorationProps> = React.memo(({ jobId }) =
3942
const featureCount = getFeatureCount(jobConfig?.dest?.results_field || '', tableItems);
4043
const colorRange = useColorRange(COLOR_RANGE.BLUE, COLOR_RANGE_SCALE.INFLUENCER, featureCount);
4144

45+
// Show the color range only if feature influence is enabled and there's more than 0 features.
46+
const showColorRange =
47+
featureCount > 0 &&
48+
isOutlierAnalysis(jobConfig?.analysis) &&
49+
jobConfig?.analysis.outlier_detection.compute_feature_influence === true;
50+
51+
const resultsField = jobConfig?.dest.results_field ?? '';
52+
53+
// Identify if the results index has a legacy feature influence format.
54+
// If feature influence was enabled for the legacy job we'll show a callout
55+
// with some additional information for a workaround.
56+
const showLegacyFeatureInfluenceFormatCallout =
57+
isOutlierAnalysis(jobConfig?.analysis) &&
58+
jobConfig?.analysis.outlier_detection.compute_feature_influence === true &&
59+
columnsWithCharts.findIndex(
60+
(d) => d.id === `${resultsField}.${FEATURE_INFLUENCE}.feature_name`
61+
) === -1;
62+
4263
return (
4364
<>
4465
{typeof jobConfig?.description !== 'undefined' && (
@@ -55,8 +76,26 @@ export const OutlierExploration: FC<ExplorationProps> = React.memo(({ jobId }) =
5576
</>
5677
)}
5778
{typeof jobConfig?.id === 'string' && <ExpandableSectionAnalytics jobId={jobConfig?.id} />}
79+
{showLegacyFeatureInfluenceFormatCallout && (
80+
<>
81+
<EuiCallOut
82+
size="s"
83+
title={i18n.translate(
84+
'xpack.ml.dataframe.analytics.outlierExploration.legacyFeatureInfluenceFormatCalloutTitle',
85+
{
86+
defaultMessage:
87+
'Color coded table cells based on feature influence are not available, because this results index uses an unsupported legacy format. Please clone an rerun the job to enable support for color coding.',
88+
}
89+
)}
90+
iconType="pin"
91+
/>
92+
<EuiSpacer size="m" />
93+
</>
94+
)}
5895
<ExpandableSectionResults
59-
colorRange={featureCount > 0 ? colorRange : undefined}
96+
colorRange={
97+
showColorRange && !showLegacyFeatureInfluenceFormatCallout ? colorRange : undefined
98+
}
6099
indexData={outlierData}
61100
indexPattern={indexPattern}
62101
jobConfig={jobConfig}

0 commit comments

Comments
 (0)