-
Notifications
You must be signed in to change notification settings - Fork 44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
stats representation via plotly in to_viz interface #335
Changes from 9 commits
a14b4e3
4efa382
671c6be
6fb41b3
5ab8005
7c68158
3663473
b6247c9
b2952bd
96e8ed4
4f1606b
61a1d51
3de6cd3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8; -*- | ||
# Copyright (c) 2023 Oracle and/or its affiliates. | ||
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ | ||
from abc import abstractmethod | ||
from typing import Union | ||
|
||
from ads.common.decorator.runtime_dependency import OptionalDependency | ||
|
||
try: | ||
from plotly.graph_objs import Figure | ||
except ModuleNotFoundError: | ||
raise ModuleNotFoundError( | ||
f"The `plotly` module was not found. Please run `pip install " | ||
f"{OptionalDependency.FEATURE_STORE}`." | ||
) | ||
|
||
|
||
class AbsFeatureStat: | ||
class ValidationFailedException(Exception): | ||
def __init__(self): | ||
pass | ||
|
||
def __init__(self): | ||
self.__validate__() | ||
|
||
@abstractmethod | ||
def __validate__(self): | ||
pass | ||
|
||
@abstractmethod | ||
def add_to_figure(self, fig: Figure, xaxis: int, yaxis: int): | ||
pass | ||
|
||
@classmethod | ||
@abstractmethod | ||
def __from_json__(cls, json_dict: dict): | ||
pass | ||
|
||
@staticmethod | ||
def get_x_y_str_axes(xaxis: int, yaxis: int) -> (): | ||
return ( | ||
("xaxis" + str(xaxis + 1)), | ||
("yaxis" + str(yaxis + 1)), | ||
("x" + str(xaxis + 1)), | ||
("y" + str(yaxis + 1)), | ||
) | ||
|
||
@classmethod | ||
def from_json( | ||
cls, json_dict: dict, ignore_errors: bool = False | ||
) -> Union["AbsFeatureStat", None]: | ||
try: | ||
return cls.__from_json__(json_dict=json_dict) | ||
except Exception as e: | ||
if ignore_errors: | ||
return None | ||
else: | ||
raise e |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8; -*- | ||
# Copyright (c) 2023 Oracle and/or its affiliates. | ||
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ | ||
from typing import List | ||
|
||
from ads.common.decorator.runtime_dependency import OptionalDependency | ||
from ads.feature_store.statistics.charts.abstract_feature_stat import AbsFeatureStat | ||
from ads.feature_store.statistics.charts.frequency_distribution import ( | ||
FrequencyDistribution, | ||
) | ||
from ads.feature_store.statistics.generic_feature_value import GenericFeatureValue | ||
|
||
try: | ||
from plotly.graph_objs import Figure | ||
except ModuleNotFoundError: | ||
raise ModuleNotFoundError( | ||
f"The `plotly` module was not found. Please run `pip install " | ||
f"{OptionalDependency.FEATURE_STORE}`." | ||
) | ||
|
||
|
||
class BoxPlot(AbsFeatureStat): | ||
CONST_MIN = "Min" | ||
CONST_MAX = "Max" | ||
CONST_QUARTILES = "Quartiles" | ||
CONST_SD = "StandardDeviation" | ||
CONST_MEAN = "Mean" | ||
CONST_BOX_PLOT_TITLE = "Box Plot" | ||
CONST_IQR = "IQR" | ||
CONST_BOX_POINTS = "box_points" | ||
|
||
class Quartiles: | ||
CONST_Q1 = "q1" | ||
CONST_Q2 = "q2" | ||
CONST_Q3 = "q3" | ||
|
||
def __init__(self, q1: float, q2: float, q3: float): | ||
self.q1 = q1 | ||
self.q2 = q2 | ||
self.q3 = q3 | ||
|
||
@classmethod | ||
def from_json(cls, json_dict: dict) -> "BoxPlot.Quartiles": | ||
return cls( | ||
json_dict.get(cls.CONST_Q1), | ||
json_dict.get(cls.CONST_Q2), | ||
json_dict.get(cls.CONST_Q3), | ||
) | ||
|
||
def __init__( | ||
self, | ||
mean: float, | ||
median: float, | ||
sd: float, | ||
q1: float, | ||
q3: float, | ||
box_points: List[float], | ||
): | ||
self.mean = mean | ||
self.median = median | ||
self.q1 = q1 | ||
self.q3 = q3 | ||
self.sd = sd | ||
self.iqr = self.q3 - self.q1 | ||
self.box_points = box_points | ||
super().__init__() | ||
|
||
def add_to_figure(self, fig: Figure, xaxis: int, yaxis: int): | ||
xaxis_str, yaxis_str, x_str, y_str = self.get_x_y_str_axes(xaxis, yaxis) | ||
fig.add_box( | ||
notched=False, | ||
boxmean=False, | ||
mean=[self.mean], | ||
median=[self.median], | ||
q1=[self.q1], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could there be scenarios where quartiles are not populated by the mlm library? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is true.....for that we have implmented validations. |
||
q3=[self.q3], | ||
sd=[self.sd], | ||
y=[self.box_points], | ||
upperfence=[self.q3 + 1.5 * self.iqr], | ||
lowerfence=[self.q1 - 1.5 * self.iqr], | ||
xaxis=x_str, | ||
yaxis=y_str, | ||
name="", | ||
jitter=0, | ||
) | ||
fig.layout.annotations[xaxis].text = self.CONST_BOX_PLOT_TITLE | ||
fig.layout[yaxis_str]["title"] = "Values" | ||
|
||
@staticmethod | ||
def get_box_points_from_frequency_distribution( | ||
frequency_distribution: FrequencyDistribution, | ||
) -> List[float]: | ||
# box_points = [] | ||
if ( | ||
frequency_distribution is not None | ||
and frequency_distribution.frequency is not None | ||
and frequency_distribution.bins is not None | ||
): | ||
return [ | ||
bin_dist | ||
for frequency, bin_dist in zip( | ||
frequency_distribution.frequency, frequency_distribution.bins | ||
) | ||
if frequency > 0 | ||
] | ||
else: | ||
return [] | ||
|
||
@classmethod | ||
def __from_json__(cls, json_dict: dict) -> "BoxPlot": | ||
quartiles = cls.Quartiles.from_json(json_dict.get(cls.CONST_QUARTILES)) | ||
return cls( | ||
mean=GenericFeatureValue.from_json(json_dict.get(cls.CONST_MEAN)).val, | ||
median=quartiles.q2, | ||
sd=GenericFeatureValue.from_json(json_dict.get(cls.CONST_SD)).val, | ||
q1=quartiles.q1, | ||
q3=quartiles.q3, | ||
box_points=json_dict.get(cls.CONST_BOX_POINTS), | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank you for adding box plot also 👍