def test_populate_options(global_var): from lux.processor.Compiler import Compiler # test for sql executor sql_df = lux.LuxSQLTable(table_name="cars") sql_df.set_intent([lux.Clause(attribute="?"), lux.Clause(attribute="milespergal")]) col_set = set() for specOptions in Compiler.populate_wildcard_options(sql_df._intent, sql_df)["attributes"]: for clause in specOptions: col_set.add(clause.attribute) assert list_equal(list(col_set), list(sql_df.columns)) sql_df.set_intent( [ lux.Clause(attribute="?", data_model="measure"), lux.Clause(attribute="milespergal"), ] ) sql_df._repr_html_() col_set = set() for specOptions in Compiler.populate_wildcard_options(sql_df._intent, sql_df)["attributes"]: for clause in specOptions: col_set.add(clause.attribute) assert list_equal( list(col_set), ["acceleration", "weight", "horsepower", "milespergal", "displacement"], )
def test_populate_options(global_var): from lux.processor.Compiler import Compiler df = pytest.car_df df.set_intent( [lux.Clause(attribute="?"), lux.Clause(attribute="MilesPerGal")]) col_set = set() for specOptions in Compiler.populate_wildcard_options(df._intent, df)["attributes"]: for clause in specOptions: col_set.add(clause.attribute) assert list_equal(list(col_set), list(df.columns)) df.set_intent([ lux.Clause(attribute="?", data_model="measure"), lux.Clause(attribute="MilesPerGal"), ]) df._ipython_display_() col_set = set() for specOptions in Compiler.populate_wildcard_options(df._intent, df)["attributes"]: for clause in specOptions: col_set.add(clause.attribute) assert list_equal( list(col_set), [ "Acceleration", "Weight", "Horsepower", "MilesPerGal", "Displacement" ], ) df.clear_intent()
def test_populate_options(): from lux.processor.Compiler import Compiler df = pd.read_csv("lux/data/car.csv") df.set_intent( [lux.Clause(attribute="?"), lux.Clause(attribute="MilesPerGal")]) col_set = set() for specOptions in Compiler.populate_wildcard_options(df._intent, df)["attributes"]: for clause in specOptions: col_set.add(clause.attribute) assert list_equal(list(col_set), list(df.columns)) df.set_intent([ lux.Clause(attribute="?", data_model="measure"), lux.Clause(attribute="MilesPerGal"), ]) df._repr_html_() col_set = set() for specOptions in Compiler.populate_wildcard_options(df._intent, df)["attributes"]: for clause in specOptions: col_set.add(clause.attribute) assert list_equal( list(col_set), [ "Acceleration", "Weight", "Horsepower", "MilesPerGal", "Displacement" ], )
def refresh_source(self, ldf): """ Loading the source into the visualizations in the VisList, then populating each visualization based on the new source data, effectively "materializing" the visualization collection. Parameters ---------- ldf : LuxDataframe Input Dataframe to be attached to the VisList Returns ------- VisList Complete VisList with fully-specified fields See Also -------- lux.vis.Vis.refresh_source Note ---- Function derives a new _inferred_intent by instantiating the intent specification on the new data """ if ldf is not None: from lux.processor.Parser import Parser from lux.processor.Validator import Validator from lux.processor.Compiler import Compiler self._source = ldf self._source.maintain_metadata() if len(self._input_lst) > 0: approx = False if self._is_vis_input(): compiled_collection = [] for vis in self._collection: vis._inferred_intent = Parser.parse(vis._intent) Validator.validate_intent(vis._inferred_intent, ldf) Compiler.compile_vis(ldf, vis) compiled_collection.append(vis) self._collection = compiled_collection else: self._inferred_intent = Parser.parse(self._intent) Validator.validate_intent(self._inferred_intent, ldf) self._collection = Compiler.compile_intent( ldf, self._inferred_intent) # Early pruning determination criteria width_criteria = len(self._collection) > (lux.config.topk + 3) length_criteria = len( ldf) > lux.config.early_pruning_sample_start if lux.config.early_pruning and width_criteria and length_criteria: # print("Apply approx to this VisList") ldf._message.add_unique( "Large search space detected: Lux is approximating the interestingness of recommended visualizations.", priority=1, ) approx = True lux.config.executor.execute(self._collection, ldf, approx=approx)
def show_all_column_vis(self): from lux.processor.Compiler import Compiler quantitative_columns = [ i for i in self.data_type if i != "quantitative" ] curr_vis = VisList([i for i in self.columns], self) if len(curr_vis) > 0: Compiler.determine_encoding(self, curr_vis[0]) if (curr_vis[0]._inferred_intent != [] and self._intent == [] and (len(quantitative_columns) == 2 or len(quantitative_columns) == 3)): self.current_vis = curr_vis self.all_column = True
def refresh_source(self, ldf): # -> Vis: """ Loading the source data into the Vis by instantiating the specification and populating the Vis based on the source data, effectively "materializing" the Vis. Parameters ---------- ldf : LuxDataframe Input Dataframe to be attached to the Vis Returns ------- Vis Complete Vis with fully-specified fields See Also -------- lux.Vis.VisList.refresh_source Note ---- Function derives a new _inferred_intent by instantiating the intent specification on the new data """ if ldf is not None: from lux.processor.Parser import Parser from lux.processor.Validator import Validator from lux.processor.Compiler import Compiler self.check_not_vislist_intent() ldf.maintain_metadata() self._source = ldf self._inferred_intent = Parser.parse(self._intent) Validator.validate_intent(self._inferred_intent, ldf) vlist = [Compiler.compile_vis(ldf, self)] lux.config.executor.execute(vlist, ldf) # Copying properties over since we can not redefine `self` within class function if len(vlist) > 0: vis = vlist[0] self.title = vis.title self._mark = vis._mark self._inferred_intent = vis._inferred_intent self._vis_data = vis.data self._min_max = vis._min_max self._postbin = vis._postbin Compiler.compile_vis(ldf, self) lux.config.executor.execute([self], ldf)
def _parse_validate_compile_intent(self): from lux.processor.Parser import Parser from lux.processor.Validator import Validator self._intent = Parser.parse(self._intent) Validator.validate_intent(self._intent, self) self.maintain_metadata() from lux.processor.Compiler import Compiler self.current_vis = Compiler.compile_intent(self, self._intent)
def recommendation(self): if self._recommendation is not None and self._recommendation == {}: from lux.processor.Compiler import Compiler self.maintain_metadata() self.current_vis = Compiler.compile_intent(self, self._intent) self.maintain_recs() return self._recommendation
def refresh_source(self, ldf): """ Loading the source into the visualizations in the VisList, then populating each visualization based on the new source data, effectively "materializing" the visualization collection. Parameters ---------- ldf : LuxDataframe Input Dataframe to be attached to the VisList Returns ------- VisList Complete VisList with fully-specified fields See Also -------- lux.vis.Vis.refresh_source Note ---- Function derives a new _inferred_intent by instantiating the intent specification on the new data """ if (ldf is not None): from lux.processor.Parser import Parser from lux.processor.Validator import Validator from lux.processor.Compiler import Compiler self._source = ldf self._source.maintain_metadata() if len(self._input_lst) > 0: if (self._is_vis_input()): compiled_collection = [] for vis in self._collection: vis._inferred_intent = Parser.parse(vis._intent) Validator.validate_intent(vis._inferred_intent, ldf) vislist = Compiler.compile_vis(ldf, vis) if (len(vislist) > 0): vis = vislist[0] compiled_collection.append(vis) self._collection = compiled_collection else: self._inferred_intent = Parser.parse(self._intent) Validator.validate_intent(self._inferred_intent, ldf) self._collection = Compiler.compile_intent( ldf, self._inferred_intent) ldf.executor.execute(self._collection, ldf)
def refresh_source(self, ldf): # -> Vis: """ Loading the source data into the Vis by instantiating the specification and populating the Vis based on the source data, effectively "materializing" the Vis. Parameters ---------- ldf : LuxDataframe Input Dataframe to be attached to the Vis Returns ------- Vis Complete Vis with fully-specified fields See Also -------- lux.Vis.VisList.refresh_source Note ---- Function derives a new _inferred_intent by instantiating the intent specification on the new data """ if ldf is not None: from lux.processor.Parser import Parser from lux.processor.Validator import Validator from lux.processor.Compiler import Compiler self.check_not_vislist_intent() ldf.maintain_metadata() self._source = ldf self._inferred_intent = Parser.parse(self._intent) Validator.validate_intent(self._inferred_intent, ldf) Compiler.compile_vis(ldf, self) lux.config.executor.execute([self], ldf)
def set_intent_on_click(self, change): from IPython.display import display, clear_output from lux.processor.Compiler import Compiler intent_action = list(self._widget.selectedIntentIndex.keys())[0] vis = self.recommendation[intent_action][self._widget.selectedIntentIndex[intent_action][0]] self.set_intent_as_vis(vis) self.maintain_metadata() self.current_vis = Compiler.compile_intent(self, self._intent) self.maintain_recs() with self.output: clear_output() display(self._widget) self._widget.observe(self.remove_deleted_recs, names="deletedIndices") self._widget.observe(self.set_intent_on_click, names="selectedIntentIndex")
def _repr_html_(self): from IPython.display import display from IPython.display import clear_output import ipywidgets as widgets try: if self._pandas_only: display(self.display_pandas()) self._pandas_only = False else: if self.index.nlevels >= 2 or self.columns.nlevels >= 2: warnings.warn( "\nLux does not currently support dataframes " "with hierarchical indexes.\n" "Please convert the dataframe into a flat " "table via `pandas.DataFrame.reset_index`.\n", stacklevel=2, ) display(self.display_pandas()) return if len(self) <= 0: warnings.warn( "\nLux can not operate on an empty dataframe.\nPlease check your input again.\n", stacklevel=2, ) display(self.display_pandas()) return self.maintain_metadata() if self._intent != [] and (not hasattr(self, "_compiled") or not self._compiled): from lux.processor.Compiler import Compiler self.current_vis = Compiler.compile_intent(self, self._intent) if lux.config.default_display == "lux": self._toggle_pandas_display = False else: self._toggle_pandas_display = True # df_to_display.maintain_recs() # compute the recommendations (TODO: This can be rendered in another thread in the background to populate self._widget) self.maintain_recs() # Observers(callback_function, listen_to_this_variable) self._widget.observe(self.remove_deleted_recs, names="deletedIndices") self._widget.observe(self.set_intent_on_click, names="selectedIntentIndex") if len(self.recommendation) > 0: # box = widgets.Box(layout=widgets.Layout(display='inline')) button = widgets.Button( description="Toggle Pandas/Lux", layout=widgets.Layout(width="140px", top="5px"), ) self.output = widgets.Output() # box.children = [button,output] # output.children = [button] # display(box) display(button, self.output) def on_button_clicked(b): with self.output: if b: self._toggle_pandas_display = not self._toggle_pandas_display clear_output() if self._toggle_pandas_display: display(self.display_pandas()) else: # b.layout.display = "none" display(self._widget) # b.layout.display = "inline-block" button.on_click(on_button_clicked) on_button_clicked(None) else: warnings.warn( "\nLux defaults to Pandas when there are no valid actions defined.", stacklevel=2, ) display(self.display_pandas()) except (KeyboardInterrupt, SystemExit): raise except Exception: warnings.warn( "\nUnexpected error in rendering Lux widget and recommendations. " "Falling back to Pandas display.\n" "Please report the following issue on Github: https://github.com/lux-org/lux/issues \n", stacklevel=2, ) warnings.warn(traceback.format_exc()) display(self.display_pandas())
def _ipython_display_(self): from IPython.display import HTML, Markdown, display from IPython.display import clear_output import ipywidgets as widgets try: if self._pandas_only: display(self.display_pandas()) self._pandas_only = False if not self.index.nlevels >= 2 or self.columns.nlevels >= 2: self.maintain_metadata() if self._intent != [] and (not hasattr(self, "_compiled") or not self._compiled): from lux.processor.Compiler import Compiler self.current_vis = Compiler.compile_intent( self, self._intent) if lux.config.default_display == "lux": self._toggle_pandas_display = False else: self._toggle_pandas_display = True # df_to_display.maintain_recs() # compute the recommendations (TODO: This can be rendered in another thread in the background to populate self._widget) self.maintain_recs() # Observers(callback_function, listen_to_this_variable) self._widget.observe(self.remove_deleted_recs, names="deletedIndices") self._widget.observe(self.set_intent_on_click, names="selectedIntentIndex") button = widgets.Button( description="Toggle Table/Lux", layout=widgets.Layout(width="200px", top="6px", bottom="6px"), ) self.output = widgets.Output() self._sampled = lux.config.executor.execute_preview(self) display(button, self.output) def on_button_clicked(b): with self.output: if b: self._toggle_pandas_display = not self._toggle_pandas_display clear_output() # create connection string to display connect_str = self.table_name connection_type = str(type(lux.config.SQLconnection)) if "psycopg2.extensions.connection" in connection_type: connection_dsn = lux.config.SQLconnection.get_dsn_parameters( ) host_name = connection_dsn["host"] host_port = connection_dsn["port"] dbname = connection_dsn["dbname"] connect_str = host_name + ":" + host_port + "/" + dbname elif "sqlalchemy.engine.base.Engine" in connection_type: db_connection = str(lux.config.SQLconnection) db_start = db_connection.index("@") + 1 db_end = len(db_connection) - 1 connect_str = db_connection[db_start:db_end] if self._toggle_pandas_display: notification = "Here is a preview of the **{}** database table: **{}**".format( self.table_name, connect_str) display(Markdown(notification), self._sampled.display_pandas()) else: # b.layout.display = "none" display(self._widget) # b.layout.display = "inline-block" button.on_click(on_button_clicked) on_button_clicked(None) except (KeyboardInterrupt, SystemExit): raise except Exception: if lux.config.pandas_fallback: warnings.warn( "\nUnexpected error in rendering Lux widget and recommendations. " "Falling back to Pandas display.\n" "Please report the following issue on Github: https://github.com/lux-org/lux/issues \n", stacklevel=2, ) warnings.warn(traceback.format_exc()) display(self.display_pandas()) else: raise
def _repr_html_(self): from IPython.display import display from IPython.display import clear_output import ipywidgets as widgets try: if (self._pandas_only): display(self.display_pandas()) self._pandas_only = False else: if (self.index.nlevels >= 2 or self.columns.nlevels >= 2): warnings.warn( "\nLux does not currently support dataframes " "with hierarchical indexes.\n" "Please convert the dataframe into a flat " "table via `pandas.DataFrame.reset_index`.\n", stacklevel=2, ) display(self.display_pandas()) return if (len(self) <= 0): warnings.warn( "\nLux can not operate on an empty dataframe.\nPlease check your input again.\n", stacklevel=2) display(self.display_pandas()) return if (len(self.columns) <= 1): warnings.warn( "\nLux defaults to Pandas when there is only a single column.", stacklevel=2) display(self.display_pandas()) return self.maintain_metadata() if (self._intent != [] and (not hasattr(self, "_compiled") or not self._compiled)): from lux.processor.Compiler import Compiler self.current_vis = Compiler.compile_intent( self, self._intent) self._toggle_pandas_display = self._default_pandas_display # Reset to Pandas Vis everytime # df_to_display.maintain_recs() # compute the recommendations (TODO: This can be rendered in another thread in the background to populate self._widget) self.maintain_recs() # box = widgets.Box(layout=widgets.Layout(display='inline')) button = widgets.Button(description="Toggle Pandas/Lux", layout=widgets.Layout(width='140px', top='5px')) output = widgets.Output() # box.children = [button,output] # output.children = [button] # display(box) display(button, output) def on_button_clicked(b): with output: if (b): self._toggle_pandas_display = not self._toggle_pandas_display clear_output() if (self._toggle_pandas_display): display(self.display_pandas()) else: # b.layout.display = "none" display(self._widget) # b.layout.display = "inline-block" button.on_click(on_button_clicked) on_button_clicked(None) except (KeyboardInterrupt, SystemExit): raise except: warnings.warn( "\nUnexpected error in rendering Lux widget and recommendations. " "Falling back to Pandas display.\n\n" "Please report this issue on Github: https://github.com/lux-org/lux/issues ", stacklevel=2) display(self.display_pandas())
def _ipython_display_(self): from IPython.display import display from IPython.display import clear_output import ipywidgets as widgets try: if self._pandas_only: display(self.display_pandas()) self._pandas_only = False else: if not self.index.nlevels >= 2 or self.columns.nlevels >= 2: self.maintain_metadata() if self._intent != [] and (not hasattr(self, "_compiled") or not self._compiled): from lux.processor.Compiler import Compiler self.current_vis = Compiler.compile_intent( self, self._intent) if lux.config.default_display == "lux": self._toggle_pandas_display = False else: self._toggle_pandas_display = True # df_to_display.maintain_recs() # compute the recommendations (TODO: This can be rendered in another thread in the background to populate self._widget) self.maintain_recs() # Observers(callback_function, listen_to_this_variable) self._widget.observe(self.remove_deleted_recs, names="deletedIndices") self._widget.observe(self.set_intent_on_click, names="selectedIntentIndex") button = widgets.Button( description="Toggle Pandas/Lux", layout=widgets.Layout(width="140px", top="5px"), ) self.output = widgets.Output() display(button, self.output) def on_button_clicked(b): with self.output: if b: self._toggle_pandas_display = not self._toggle_pandas_display clear_output() if self._toggle_pandas_display: display(self.display_pandas()) else: # b.layout.display = "none" display(self._widget) # b.layout.display = "inline-block" button.on_click(on_button_clicked) on_button_clicked(None) except (KeyboardInterrupt, SystemExit): raise except Exception: if lux.config.pandas_fallback: warnings.warn( "\nUnexpected error in rendering Lux widget and recommendations. " "Falling back to Pandas display.\n" "Please report the following issue on Github: https://github.com/lux-org/lux/issues \n", stacklevel=2, ) warnings.warn(traceback.format_exc()) display(self.display_pandas()) else: raise
def test_populate_options(global_var): lux.config.set_executor_type("Pandas") from lux.processor.Compiler import Compiler df = pytest.car_df df.set_intent( [lux.Clause(attribute="?"), lux.Clause(attribute="MilesPerGal")]) col_set = set() for specOptions in Compiler.populate_wildcard_options(df._intent, df)["attributes"]: for clause in specOptions: col_set.add(clause.attribute) assert list_equal(list(col_set), list(df.columns)) df.set_intent([ lux.Clause(attribute="?", data_model="measure"), lux.Clause(attribute="MilesPerGal"), ]) df._repr_html_() col_set = set() for specOptions in Compiler.populate_wildcard_options(df._intent, df)["attributes"]: for clause in specOptions: col_set.add(clause.attribute) assert list_equal( list(col_set), [ "Acceleration", "Weight", "Horsepower", "MilesPerGal", "Displacement" ], ) df.clear_intent() # test for sql executor connection = psycopg2.connect( "host=localhost dbname=postgres user=postgres password=lux") lux.config.set_SQL_connection(connection) sql_df = lux.LuxSQLTable(table_name="cars") sql_df.set_intent( [lux.Clause(attribute="?"), lux.Clause(attribute="milespergal")]) col_set = set() for specOptions in Compiler.populate_wildcard_options( sql_df._intent, sql_df)["attributes"]: for clause in specOptions: col_set.add(clause.attribute) assert list_equal(list(col_set), list(sql_df.columns)) sql_df.set_intent([ lux.Clause(attribute="?", data_model="measure"), lux.Clause(attribute="milespergal"), ]) sql_df._repr_html_() col_set = set() for specOptions in Compiler.populate_wildcard_options( sql_df._intent, sql_df)["attributes"]: for clause in specOptions: col_set.add(clause.attribute) assert list_equal( list(col_set), [ "acceleration", "weight", "horsepower", "milespergal", "displacement" ], )