We support four plot types: Scatter, Line, Bar and Histograms.

In order to plot data, you first need at least one table in your interface, which is used to define the data which will be used for the plot axes. You can also plot data which spans across multiple tables, but we’ll focus on the single table case for now.

So let’s dive in and go through each plot type 🤿

Scatter Graphs

Scatter graphs can be used to plot two numerical columns against each other. For example, let’s log the following:

Open in your console
import unify
import random

for i in range(10):
    unify.log(
        x=i,
        y=i+random.uniform(-0.25, 0.25)
    )

We can then select the x column for the x-axis and the y column for the y-axis.

We can also overlay several plots on the graph, by selecting another column to group by (based on value equality, the same as grouping in the table). Let’s make an example.

Open in your console
import unify
import random

gender_factors = {"male": 2000, "female": 1000}
for gender in ["male", "female"]:
    for age in range(20, 55):
        age += random.randint(-5, 5)
        unify.log(
            gender=gender,
            age=age,
            salary=(
                age*500 +
                age*gender_factors[gender]*random.random()
            ),
        )

We can then select age for the x-axis, salary for the y-axis and group by gender. We can also add a line of best fit to each group in the plot.

If we want to group across multiple independent variables, we can just create a new derived column to express the desired group. Let’s assume we also log the nationality of the person.

Open in your console
import unify
import random

gender_factors = {"male": 1500, "female": 750}
loc_offsets = {"UK": 15000, "US": 45000}
for gender in ["male", "female"]:
    for loc in ["UK", "US"]:
        for age in range(20, 55):
            unify.log(
                gender=gender,
                nationality=loc,
                age=age,
                salary=(
                    age*500 +
                    age*gender_factors[gender]*random.random() +
                    loc_offsets[loc]*random.random()
                ),
            )

In order to plot against both variables, let’s create a new derived column called gender + nationality with the equation gender + nationality. We can then group by this new column.

We could then create three plots for example: one which groups by gender, one which groups by location and one which groups by both. We can then save this and revisit this dashboard again any time in future, whenever more data is added into the project.

Line Graphs

Line graphs are similar to scatter graphs, but a line is drawn between each from left to right. This makes them especially suitable for plotting time-series data. Let’s take the same example as before, but plot it as a line graph.

Open in your console
import unify
import random

for i in range(10):
    unify.log(
        x=i,
        y=i+random.uniform(-0.25, 0.25)
    )

As before, we can also group by another column. Let’s imagine we want to plot the speed of different models across time, which are being continually streamed.

Open in your console
import unify
import random
from datetime import datetime

model_speeds = {
    "llama-3.1-8b-chat": 12,
    "llama-3.1-70b-chat": 7,
    "llama-3.1-405b-chat": 4
}
while True:
    for model, speed in model_speeds.items():
        unify.log(
            model=model,
            time=datetime.now().isoformat(),
            speed=speed+random.uniform(-3, 3)
        )

We can then select time for the x-axis, speed for the y-axis and group by model.

By default, new data will not be loaded into the interface unless something triggers a reload, such as filtering, grouping or sorting. The table can be refreshed manually using the refresh button, or streaming mode can be turned on in order to continually stream new data into the platform. if we want a moving window of the runtime, we can turn streaming on for both the table and the plot, and then limit the time horizon to the last 5 minutes, for example.

Similar to the derived identity column before, we can create a derived endpoint column to plot a unique line for each model + provider combination. Let’s create some dummy data for this scenario:

Open in your console
import unify
import random

model_speeds = {
    "llama-3.1-8b-chat": 12,
    "llama-3.1-70b-chat": 7,
    "llama-3.1-405b-chat": 4
}
provider_speeds = {
    "fireworks-ai": 10,
    "together-ai": 9,
    "aws-bedrock": 8
}
for i in range(25):
    for model, model_speed in model_speeds.items():
        for provider, provider_speed in provider_speeds.items():
            unify.log(  
                model=model,
                provider=provider,
                time=i,
                speed=(
                    model_speed + 
                    provider_speed + 
                    random.uniform(-2, 2)
                )
            )

Let’s then create the derived column and plot results for each unique endpoint.

Bar Charts

Bar charts are different to line graphs and scatter graphs. The x axis does not represent individual numerical values, but instead represents groups of data of any type (which share the same value). The y axis then represents a reduction across the data in each group (bar) in the graph.

For example, let’s say we’ve run two experiments, which vary the tool use and the system message.

Open in your console
import unify
import random

base_msg = "You are a helpful assistant."
for tool_use in [True, False]:
    with unify.Params(tool_use=tool_use):
        for sys_msg in [
            base_msg,
            base_msg + " You can use tools.",
            base_msg + " You can use tools and search the web."
        ]:
            with unify.Params(sys_msg=sys_msg):  
                for example_idx in range(10):
                    unify.log(
                        example_idx=example_idx,
                        score=random.uniform(0, 10)
                    )

We can then create a bar chart which groups by the system message and tool use. Let’s plot the mean score on the y-axis, to see how each of our experiments performed across the 10 examples.

Histograms

Finally, we can also plot histograms, which take a single numeric column, and then bucket this data into n bins on the x-axis, and plot the count of data in each bin on the y-axis.

For example, let’s say we want to see the distribution of user traffic over the past year. Has our product been gaining traction?

Open in your console
import unify
import random

n = 10
for month in range(1, 13):
    num_queries = random.randint(month*n, (month+10)*n)
    unify.create_logs(
        entries=[
            {
                "date": date(
                    2025, month, random.randint(1, 28)
                ).isoformat()
            }
            for _ in range(num_queries)
        ]
    )

Let’s take a look at the corresponding histogram.

We can see that the usage has been steadily increasing throughout the year, good stuff! 📈