import { useState , useEffect } from 'react' ; import { isClassificationEvaluateResponse , ResultsSearchQuery , RocCurveItem , ANALYSIS_CONFIG_TYPE , } from '../../../../common/analytics' ; import { isKeywordAndTextType } from '../../../../common/fields' ; import { getDependentVar , getPredictionFieldName , loadEvalData , DataFrameAnalyticsConfig , } from '../../../../common' ; import { ACTUAL_CLASS_ID , OTHER_CLASS_ID } from './column_data' ; import { isTrainingFilter } from './is_training_filter' ; const AUC_VALUE_LABEL = 'AUC' ; const AUC_ROUNDING_VALUE = 100000 ; const ROC_CLASS_NAME = 'ROC' ; const BINARY_CLASSIFICATION_THRESHOLD = 2 ; interface RocCurveDataRow extends RocCurveItem { class_name : string ; } export const useRocCurve = ( jobConfig , searchQuery , columns ) => { const classificationClasses = columns . filter ( ( d ) => d !== ACTUAL_CLASS_ID && d !== OTHER_CLASS_ID ) ; if ( classificationClasses . length <= BINARY_CLASSIFICATION_THRESHOLD ) { classificationClasses . splice ( 1 ) ; } const [ rocCurveData , setRocCurveData ] = useState < RocCurveDataRow [ ] > ( [ ] ) ; const [ isLoading , setIsLoading ] = useState < boolean > ( false ) ; const [ error , setError ] = useState < null | string [ ] > ( null ) ; useEffect ( ( ) => { async function loadRocCurveData ( ) { setIsLoading ( true ) ; const dependentVariable = getDependentVar ( jobConfig . analysis ) ; const resultsField = jobConfig . dest . results_field ; const newRocCurveData = [ ] ; let requiresKeyword = false ; const errors = [ ] ; try { requiresKeyword = isKeywordAndTextType ( dependentVariable ) ; } catch ( e ) { console . error ( 'Unable to load new field types' , e ) ; } for ( let i = 0 ; i < classificationClasses . length ; i ++ ) { const rocCurveClassName = classificationClasses [ i ] ; const evalData = await loadEvalData ( { isTraining : isTrainingFilter ( searchQuery , resultsField ) , index : jobConfig . dest . index , dependentVariable , resultsField , predictionFieldName : getPredictionFieldName ( jobConfig . analysis ) , searchQuery , jobType : ANALYSIS_CONFIG_TYPE . CLASSIFICATION , requiresKeyword , rocCurveClassName , includeMulticlassConfusionMatrix : false , } ) ; if ( evalData . success === true && evalData . eval && isClassificationEvaluateResponse ( evalData . eval ) ) { const auc = evalData . eval ?. classification ?. auc_roc ?. value || 0 ; const rocCurveClassLabel = classificationClasses . length > BINARY_CLASSIFICATION_THRESHOLD ? classificationClasses [ i ] : ROC_CLASS_NAME ; const rocCurveDataForClass = ( evalData . eval ?. classification ?. auc_roc ?. curve || [ ] ) . map ( ( d ) => ( { class_name : `${ rocCurveClassLabel } (${ AUC_VALUE_LABEL }: ${ Math . round ( auc * AUC_ROUNDING_VALUE ) / AUC_ROUNDING_VALUE })` , ... d , } ) ) ; newRocCurveData . push ( ... rocCurveDataForClass ) ; } else if ( evalData . error !== null ) { errors . push ( evalData . error ) ; } } setError ( errors . length > 0 ? errors : null ) ; setRocCurveData ( newRocCurveData ) ; setIsLoading ( false ) ; } loadRocCurveData ( ) ; } , [ JSON . stringify ( [ jobConfig , searchQuery , columns ] ) ] ) ; return { rocCurveData , classificationClasses : classificationClasses . length > BINARY_CLASSIFICATION_THRESHOLD ? classificationClasses : [ ROC_CLASS_NAME ] , error , isLoading , } ; } ;