Customizing Visualizations

Before we go into more details on how to construct complex visualizations, let us explain how one can customize the plots generated by Vizagrams specification.

using Vizagrams
using DataFrames
using Statistics
using Random
using VegaDatasets
df = DataFrame(dataset("cars"));

# We need to drop missing values, as Vizagrams does not handle them yet.
df = dropmissing(df);

When creating a plot in Vizagrams, many defaults are guessed in order to make the specification less verbose. Yet, if one wishes, it is possible to alter such deafults in order to produce custom visuals.

1. Legends

When visualizations become more complex, so do their legends. Consider, for example, the scatter plot with faces as marks.

plt = Plot(
    title="MyPlot",
    data=df,
    encodings=(
        x = (field = :Horsepower,),
        y = (field = :Displacement,),
        color = (field = :Origin, scale_range=:tableau_superfishel_stone),
        smile = (field = :Cylinders, scale_range=(-1,1), legend=(fmark=x->Face(size=7,smile=x),)),
    ),
    graphic = ∑() do row
        T(row[:x],row[:y])U(5)Face(headstyle=S(:fill=>row[:color]),smile=row[:smile])
    end
)


draw(plt, height=400)
Example block output

When a user defines a new encoder, such as smile, by default, no legend will be drawn. If the user wants a legend, it is possible to specify a function, through the fmark argument, which takes the values encoded and draws a mark. Another option is for users to draw the legends as a separate diagram, and incorporate it into the plot.

In the example above, we have used the fmark option. Let us now create a new customized legend.

plt = Plot(
    title="MyPlot",
    data=df,
    encodings=(
        x = (field = :Horsepower,),
        y = (field = :Displacement,),
        color = (field = :Origin, scale_range=:tableau_superfishel_stone),
        smile = (field = :Cylinders, scale_range=(-1,1)),
    ),
    graphic = ∑() do row
        T(row[:x],row[:y])U(5)Face(headstyle=S(:fill=>row[:color]),smile=row[:smile])
    end
)


legend_title = S(:fontWeight => "bold")TextMark(fontfamily="Helvetica",text="Smile",fontsize=8)
legend_marks =
        Face(smile=-1) ↓
        (T(0,-0.4),TextMark(text="Cylinders = 3",fontsize=0.6)) →
        (T(2,0),TextMark(text="...",fontsize=1)) →
        (T(2,0),Face(smile=1) ↓
        (T(0,-0.4),TextMark(text="Cylinders = 3",fontsize=0.6)))
legend = legend_title ↓ (T(0,-10),U(8)legend_marks)

draw(plt + T(plt.config.figsize[1]+30,130)legend, height=400)
Example block output

2. Frames and Axes

Through the config argument in the graphic specification, users can thoroughly customize the frame and axes of plots.

gdf = combine(groupby(df,[:Year,:Origin]),:Horsepower=>mean,:Miles_per_Gallon=>mean,:Cylinders=>median)

gdf = sort(gdf,:Year)

plt = Plot(
    config=(
            frame_style=S(:stroke=>:white),
            xgrid = (;style=S(:strokeWidth=>30,:strokeOpacity=>0.05)),
            xaxis=(
                    title="years",
                    titleangle=π/2,
                    titlefontsize=8,
                    ticktextangle=π/2,
                    ticktexts=collect(1970:1982),
                    axisarrow=S(:stroke=>:red,:fill=>:red)Arrow(pts=[[0,0],[300,0]],headsize=5),
            ),
            ygrid=NilD(),
            yaxis=(
                    title=TextMark(text="Mean Horsepower",fontsize=7,style= S(:fontWeight=>:bold), angle=π/2),
                    ticktextangle=π/2,
                    tickmark=T(2,0)Square(l=6),
            ),
        ),
    data = gdf,
    encodings=(
        x=(field=:Year,),
        y=(field=:Horsepower_mean,),
        color=(field=:Origin,),
        size = (field = :Cylinders_median,),
    ),
    graphic = S(:opacity=>0.5,:stroke=>:black)Circle()
)

draw(plt,height=400,pad=30)
Example block output

3. Titles

At last, we have the title of a plot. The simplest way to customize a title is to omit is from the graphic specification, and instead join it to the plot using the diagram opeartions.

plt = Plot(
    data=df,
    encodings=(
        x = (field = :Horsepower,),
        y = (field = :Displacement,),
        size = (field = :Cylinders,),
    ),
    graphic = S(:fill=>:steelblue,:opacity=>0.2,:stroke=>:black)Circle()
)

maintitle = S(:fontWeight=>:bold)TextMark(text="Main Title", anchor=:e,fontfamily="monospace")
subtitle = S(:fontStyle=>:italic)TextMark(text="Subtitle", anchor=:e, fontsize=8,fontfamily="monospace")

title = maintitle ↓ (T(0,-5),subtitle)

d = plt ↑ title

draw(d, height=400)
Example block output