Skip to content

Commit

Permalink
[ML] Fix feature importance column.
Browse files Browse the repository at this point in the history
  • Loading branch information
walterra committed Apr 23, 2020
1 parent 8ba23f1 commit 748cc88
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 29 deletions.
42 changes: 28 additions & 14 deletions x-pack/plugins/ml/public/application/components/data_grid/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@
*/

import moment from 'moment-timezone';
import { useMemo } from 'react';
import { useEffect, useMemo } from 'react';

import { EuiDataGridSorting, EuiDataGridStyle } from '@elastic/eui';
import {
EuiDataGridCellValueElementProps,
EuiDataGridSorting,
EuiDataGridStyle,
} from '@elastic/eui';

import {
IndexPattern,
Expand Down Expand Up @@ -101,12 +105,15 @@ export const getDataGridSchemasFromFieldTypes = (fieldTypes: FieldTypes, results

if (
field === `${resultsField}.${OUTLIER_SCORE}` ||
field === `${resultsField}.${FEATURE_INFLUENCE}` ||
field === `${resultsField}.${FEATURE_IMPORTANCE}`
field.includes(`${resultsField}.${FEATURE_INFLUENCE}`)
) {
schema = 'numeric';
}

if (field.includes(`${resultsField}.${FEATURE_IMPORTANCE}`)) {
schema = 'json';
}

return { id: field, schema, isSortable };
});
};
Expand Down Expand Up @@ -139,11 +146,12 @@ export const useRenderCellValue = (
indexPattern: IndexPattern | undefined,
pagination: IndexPagination,
tableItems: DataGridItem[],
resultsField: string,
cellPropsCallback?: (
columnId: string,
cellValue: any,
fullItem: Record<string, any>,
setCellProps: any
setCellProps: EuiDataGridCellValueElementProps['setCellProps']
) => void
): RenderCellValue => {
const renderCellValue: RenderCellValue = useMemo(() => {
Expand All @@ -154,7 +162,7 @@ export const useRenderCellValue = (
}: {
rowIndex: number;
columnId: string;
setCellProps: any;
setCellProps: EuiDataGridCellValueElementProps['setCellProps'];
}) => {
const adjustedRowIndex = rowIndex - pagination.pageIndex * pagination.pageSize;

Expand All @@ -175,10 +183,9 @@ export const useRenderCellValue = (
}

function getCellValue(cId: string) {
if (cId.includes(`.${FEATURE_IMPORTANCE}.`)) {
const results = getNestedProperty(tableItems[adjustedRowIndex], 'ml', null);
const featureImportanceField = cId.replace('ml.', '');
return results[featureImportanceField];
if (cId.includes(`.${FEATURE_INFLUENCE}.`)) {
const results = getNestedProperty(tableItems[adjustedRowIndex], resultsField, null);
return results[cId.replace(`${resultsField}.`, '')];
}

return tableItems.hasOwnProperty(adjustedRowIndex)
Expand All @@ -188,6 +195,17 @@ export const useRenderCellValue = (

const cellValue = getCellValue(columnId);

// React by default doesn't all us to use a hook in a callback.
// However, this one will be passed on to EuiDataGrid and its docs
// recommend wrapping `setCellProps` in a `useEffect()` hook
// so we're ignoring the linting rule here.
// eslint-disable-next-line react-hooks/rules-of-hooks
useEffect(() => {
if (typeof cellPropsCallback === 'function') {
cellPropsCallback(columnId, cellValue, fullItem, setCellProps);
}
}, [columnId, cellValue]);

if (typeof cellValue === 'object' && cellValue !== null) {
return JSON.stringify(cellValue);
}
Expand Down Expand Up @@ -217,10 +235,6 @@ export const useRenderCellValue = (
return JSON.stringify(cellValue);
}

if (typeof cellPropsCallback === 'function') {
cellPropsCallback(columnId, cellValue, fullItem, setCellProps);
}

return cellValue;
};
}, [indexPattern?.fields, pagination.pageIndex, pagination.pageSize, tableItems]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

export const DEFAULT_RESULTS_FIELD = 'ml';
export const FEATURE_IMPORTANCE = 'feature_importance';
export const FEATURE_INFLUENCE = 'feature_influence';
export const OUTLIER_SCORE = 'outlier_score';
Original file line number Diff line number Diff line change
Expand Up @@ -214,15 +214,11 @@ export const getDefaultFieldsFromJobCaps = (
}`;

if ((numTopFeatureImportanceValues ?? 0) > 0 && needsDestIndexFields === true) {
featureImportanceFields.push(
...fields
.filter(d => !jobConfig.analyzed_fields.excludes.includes(d.id))
.map(d => ({
id: `${resultsField}.${FEATURE_IMPORTANCE}.${d.id}`,
name: `${resultsField}.${FEATURE_IMPORTANCE}.${d.name}`,
type: KBN_FIELD_TYPES.NUMBER,
}))
);
featureImportanceFields.push({
id: `${resultsField}.${FEATURE_IMPORTANCE}`,
name: `${resultsField}.${FEATURE_IMPORTANCE}`,
type: KBN_FIELD_TYPES.UNKNOWN,
});
}

// Only need to add these fields if we didn't use dest index pattern to get the fields
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
import { SavedSearchQuery } from '../../../../../contexts/ml';

import { getIndexData, getIndexFields, DataFrameAnalyticsConfig } from '../../../../common';
import { FEATURE_IMPORTANCE } from '../../../../common/constants';
import { DEFAULT_RESULTS_FIELD, FEATURE_IMPORTANCE } from '../../../../common/constants';
import { sortExplorationResultsFields, ML__ID_COPY } from '../../../../common/fields';

export const useExplorationResults = (
Expand Down Expand Up @@ -60,7 +60,8 @@ export const useExplorationResults = (
const renderCellValue = useRenderCellValue(
indexPattern,
dataGrid.pagination,
dataGrid.tableItems
dataGrid.tableItems,
jobConfig?.dest.results_field ?? DEFAULT_RESULTS_FIELD
);

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
import { SavedSearchQuery } from '../../../../../contexts/ml';

import { getIndexData, getIndexFields, DataFrameAnalyticsConfig } from '../../../../common';
import { FEATURE_INFLUENCE } from '../../../../common/constants';
import { DEFAULT_RESULTS_FIELD, FEATURE_INFLUENCE } from '../../../../common/constants';
import { sortExplorationResultsFields, ML__ID_COPY } from '../../../../common/fields';

import { getFeatureCount, getOutlierScoreFieldName } from './common';
Expand Down Expand Up @@ -81,15 +81,16 @@ export const useOutlierData = (
indexPattern,
dataGrid.pagination,
dataGrid.tableItems,
jobConfig?.dest.results_field ?? DEFAULT_RESULTS_FIELD,
(columnId, cellValue, fullItem, setCellProps) => {
const resultsField = jobConfig?.dest.results_field ?? '';

const split = columnId.split('.');
let backgroundColor;

// column with feature values get color coded by its corresponding influencer value
if (fullItem[`${resultsField}.${FEATURE_INFLUENCE}.${columnId}`] !== undefined) {
backgroundColor = colorRange(fullItem[`${resultsField}.${FEATURE_INFLUENCE}.${columnId}`]);
if (fullItem[resultsField][`${FEATURE_INFLUENCE}.${columnId}`] !== undefined) {
backgroundColor = colorRange(fullItem[resultsField][`${FEATURE_INFLUENCE}.${columnId}`]);
}

// column with influencer values get color coded by its own value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { i18n } from '@kbn/i18n';
import { DeepReadonly } from '../../../../../../../common/types/common';
import { DataFrameAnalyticsConfig, isOutlierAnalysis } from '../../../../common';
import { isClassificationAnalysis, isRegressionAnalysis } from '../../../../common/analytics';
import { DEFAULT_RESULTS_FIELD } from '../../../../common/constants';
import {
CreateAnalyticsFormProps,
DEFAULT_NUM_TOP_FEATURE_IMPORTANCE_VALUES,
Expand Down Expand Up @@ -214,7 +215,7 @@ const getAnalyticsJobMeta = (config: CloneDataFrameAnalyticsConfig): AnalyticsJo
},
results_field: {
optional: true,
defaultValue: 'ml',
defaultValue: DEFAULT_RESULTS_FIELD,
},
},
model_memory_limit: {
Expand Down

0 comments on commit 748cc88

Please sign in to comment.