hat will hold the data that you want to visualize.Build a custom materializer for this custom class with the visualization logic implemented in the save_visualizations() method.

Return your custom class from any of your ZenML steps.

Example: Facets Data Skew Visualization

As an example, have a look at the models, materializers, and steps of the Facets Integration, which can be used to visualize the data skew between multiple Pandas DataFrames:

1. Custom Class The FacetsComparison is the custom class that holds the data required for the visualization.

class FacetsComparison(BaseModel):

datasets: List[Dict[str, Union[str, pd.DataFrame]]]

2. Materializer The FacetsMaterializer is a custom materializer that only handles this custom class and contains the corresponding visualization logic.

class FacetsMaterializer(BaseMaterializer):

ASSOCIATED_TYPES = (FacetsComparison,)

ASSOCIATED_ARTIFACT_TYPE = ArtifactType.DATA_ANALYSIS

def save_visualizations(

self, data: FacetsComparison

) -> Dict[str, VisualizationType]:

html = ...  # Create a visualization for the custom type

visualization_path = os.path.join(self.uri, VISUALIZATION_FILENAME)

with fileio.open(visualization_path, "w") as f:

f.write(html)

return {visualization_path: VisualizationType.HTML}

3. Step There are three different steps in the facets integration that can be used to create FacetsComparisons for different sets of inputs. E.g., the facets_visualization_step below takes two DataFrames as inputs and builds a FacetsComparison object out of them:

@step

def facets_visualization_step(

reference: pd.DataFrame, comparison: pd.DataFrame

) -> FacetsComparison:  # Return the custom type from your step

return FacetsComparison(

datasets=[

{"name": "reference", "table": reference},

{"name": "comparison", "table": comparison},

This is what happens now under the hood when you add the facets_visualization_step into your pipeline:

The step creates and returns a FacetsComparison.