Skip to content

Helper function for altair exports #8

Open

Description

@timvink

altair has good support for exporting vega schemas (https://altair-viz.github.io/user_guide/saving_charts.html?highlight=to_).

Of course you could just use chart.save('chart.svg') and insert that into a mkdocs page. But you want to want update the data later on and use the same chart.

Manually copy pasting the schema to a file is a hassle. Write a helper function to:

save_mkdocs_chart(chart, name="", docs_folder="../docs", json_path="docs/assets/charts/", data_path="docs/assets/charts/data")

The docs_folders could be auto-detected by traversing upward, finding mkdocs.yml and reading the docs_dir entry (if not present then docs/).

The json_path is relative to the docs_folder and can have a default "docs/assets/charts/"

The data_path is relative to the docs_folder and can have a "docs/assets/charts/data" default. This will only work if we can access the data object in the altair chart instance, which we can then write to .csv.

Activity

  1. ewellinger commented on Jun 1, 2023

    @ewellinger

    This might need to be tweaked somewhat, but I created this helper function that roughly follows the logic you're suggesting here:

    import json
    from pathlib import Path
    
    from altair import Chart
    from pydantic import BaseModel, DirectoryPath, validator
    
    
    class ChartParams(BaseModel):
        output_dir: DirectoryPath
        data_file: str
        plot_name: str
    
        @validator("data_file")
        def validate_data_file(cls, val, values):
            if "output_dir" in values:
                full_path = values["output_dir"].absolute() / val
                if not full_path.exists():
                    raise ValueError("data_file does not exist")
            return val
    
        @validator("plot_name")
        def validate_plot_name(cls, val):
            if not val.endswith("json"):
                raise ValueError(f"plot_name must end with .json")
            return val
    
        @property
        def plot_path(self):
            return self.output_dir / self.plot_name
    
    
    def save_chart(chart: Chart, output_dir: Path, data_file: str = "results.csv", plot_name: str = "plot.json") -> None:
        params = ChartParams(output_dir=output_dir, data_file=data_file, plot_name=plot_name)
    
        # Convert the plot to JSON
        plot = json.loads(chart.to_json())
    
        del plot["datasets"]
        plot["data"] = {"url": data_file}
        with open(params.plot_path, "w") as fo:
            json.dump(plot, fo)

    This assumes you're storing the plot in the same directory as the CSV file containing the data.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions