[ML] DFAnalytics results: ensure ml result fields are shown in data grid (#68305)

* wip: ensure top classes and influencer result col show up correctly

* ensure ml subFields columns are populated
This commit is contained in:
Melissa Alvarez 2020-06-08 11:19:01 -04:00 committed by GitHub
parent bc3918671c
commit e2f11e9fe9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 43 additions and 7 deletions

View file

@ -29,6 +29,7 @@ import {
FEATURE_IMPORTANCE,
FEATURE_INFLUENCE,
OUTLIER_SCORE,
TOP_CLASSES,
} from '../../data_frame_analytics/common/constants';
import { formatHumanReadableDateTimeSeconds } from '../../util/date_utils';
import { getNestedProperty } from '../../util/object_utils';
@ -110,7 +111,10 @@ export const getDataGridSchemasFromFieldTypes = (fieldTypes: FieldTypes, results
schema = 'numeric';
}
if (field.includes(`${resultsField}.${FEATURE_IMPORTANCE}`)) {
if (
field.includes(`${resultsField}.${FEATURE_IMPORTANCE}`) ||
field.includes(`${resultsField}.${TOP_CLASSES}`)
) {
schema = 'json';
}

View file

@ -228,6 +228,16 @@ export const getPredictionFieldName = (
return predictionFieldName;
};
export const getNumTopClasses = (
analysis: AnalysisConfig
): ClassificationAnalysis['classification']['num_top_classes'] => {
let numTopClasses;
if (isClassificationAnalysis(analysis) && analysis.classification.num_top_classes !== undefined) {
numTopClasses = analysis.classification.num_top_classes;
}
return numTopClasses;
};
export const getNumTopFeatureImportanceValues = (
analysis: AnalysisConfig
):

View file

@ -7,4 +7,5 @@
export const DEFAULT_RESULTS_FIELD = 'ml';
export const FEATURE_IMPORTANCE = 'feature_importance';
export const FEATURE_INFLUENCE = 'feature_influence';
export const TOP_CLASSES = 'top_classes';
export const OUTLIER_SCORE = 'outlier_score';

View file

@ -5,6 +5,7 @@
*/
import {
getNumTopClasses,
getNumTopFeatureImportanceValues,
getPredictedFieldName,
getDependentVar,
@ -18,7 +19,7 @@ import { Field } from '../../../../common/types/fields';
import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '../../../../../../../src/plugins/data/public';
import { newJobCapsService } from '../../services/new_job_capabilities_service';
import { FEATURE_IMPORTANCE, FEATURE_INFLUENCE, OUTLIER_SCORE } from './constants';
import { FEATURE_IMPORTANCE, FEATURE_INFLUENCE, OUTLIER_SCORE, TOP_CLASSES } from './constants';
export type EsId = string;
export type EsDocSource = Record<string, any>;
@ -177,6 +178,7 @@ export const getDefaultFieldsFromJobCaps = (
const featureImportanceFields = [];
const featureInfluenceFields = [];
const topClassesFields = [];
const allFields: any = [];
let type: ES_FIELD_TYPES | undefined;
let predictedField: string | undefined;
@ -207,13 +209,14 @@ export const getDefaultFieldsFromJobCaps = (
type = newJobCapsService.getFieldById(dependentVariable)?.type;
const predictionFieldName = getPredictionFieldName(jobConfig.analysis);
const numTopFeatureImportanceValues = getNumTopFeatureImportanceValues(jobConfig.analysis);
const numTopClasses = getNumTopClasses(jobConfig.analysis);
const defaultPredictionField = `${dependentVariable}_prediction`;
predictedField = `${resultsField}.${
predictionFieldName ? predictionFieldName : defaultPredictionField
}`;
if ((numTopFeatureImportanceValues ?? 0) > 0 && needsDestIndexFields === true) {
if ((numTopFeatureImportanceValues ?? 0) > 0) {
featureImportanceFields.push({
id: `${resultsField}.${FEATURE_IMPORTANCE}`,
name: `${resultsField}.${FEATURE_IMPORTANCE}`,
@ -221,6 +224,14 @@ export const getDefaultFieldsFromJobCaps = (
});
}
if ((numTopClasses ?? 0) > 0) {
topClassesFields.push({
id: `${resultsField}.${TOP_CLASSES}`,
name: `${resultsField}.${TOP_CLASSES}`,
type: KBN_FIELD_TYPES.UNKNOWN,
});
}
// Only need to add these fields if we didn't use dest index pattern to get the fields
if (needsDestIndexFields === true) {
allFields.push(
@ -234,7 +245,12 @@ export const getDefaultFieldsFromJobCaps = (
}
}
allFields.push(...fields, ...featureImportanceFields, ...featureInfluenceFields);
allFields.push(
...fields,
...featureImportanceFields,
...featureInfluenceFields,
...topClassesFields
);
allFields.sort(({ name: a }: { name: string }, { name: b }: { name: string }) =>
sortExplorationResultsFields(a, b, jobConfig)
);

View file

@ -19,7 +19,11 @@ import {
import { SavedSearchQuery } from '../../../../../contexts/ml';
import { getIndexData, getIndexFields, DataFrameAnalyticsConfig } from '../../../../common';
import { DEFAULT_RESULTS_FIELD, FEATURE_IMPORTANCE } from '../../../../common/constants';
import {
DEFAULT_RESULTS_FIELD,
FEATURE_IMPORTANCE,
TOP_CLASSES,
} from '../../../../common/constants';
import { sortExplorationResultsFields, ML__ID_COPY } from '../../../../common/fields';
export const useExplorationResults = (
@ -47,8 +51,9 @@ export const useExplorationResults = (
25,
// reduce default selected rows from 20 to 8 for performance reasons.
8,
// by default, hide feature-importance columns and the doc id copy
(d) => !d.includes(`.${FEATURE_IMPORTANCE}.`) && d !== ML__ID_COPY
// by default, hide feature-importance and top-classes columns and the doc id copy
(d) =>
!d.includes(`.${FEATURE_IMPORTANCE}.`) && !d.includes(`.${TOP_CLASSES}.`) && d !== ML__ID_COPY
);
useEffect(() => {