Scales
Axes and legends in the Grammar of Graphics can be customized using scales.
A scale is always paired with aesthetic mappings set within .qp.s.aes
. If
an explicit scale is not provided by .qp.s.scale
for a given aesthetic, a
default scale is chosen.
Examples
First, a basic plot with default scales chosen for x, y, and fill.
.qp.go[400;300]
.qp.point[([]x: .st.gen.normal 1000; y: .st.gen.normal 1000; z: 1000?`a`b`c); `x; `y]
.qp.s.aes[`fill; `z]
Next, the x and y scale can be changed to model a different distribution. The default scale
for numeric data is .gg.scale.linear
.
.qp.go[400;300]
.qp.point[([]x: .st.gen.normal 1000; y: .st.gen.normal 1000; z: 1000?`a`b`c); `x; `y]
.qp.s.aes[`fill; `z] ,
.qp.s.scale[`x; .gg.scale.log] ,
.qp.s.scale[`y; .gg.scale.power 2]
The fill scale can be changed to use any preferred colours. The default scale for categorical
fill columns is .gg.colour.cat10
which is 10 visually distinct colours. Here, we continue
to use a categorical colour scale, but change the colour mapping to use a Colour Brewer
3-value palette from Set1.
.qp.go[400;300]
.qp.point[([]x: .st.gen.normal 1000; y: .st.gen.normal 1000; z: 1000?`a`b`c); `x; `y]
.qp.s.aes[`fill; `z] ,
.qp.s.scale[`x; .gg.scale.log] ,
.qp.s.scale[`y; .gg.scale.power 2] ,
.qp.s.scale[`fill; .gg.scale.colour.cat .gg.colour.brewer[`Set1;3]]
There are plenty of settings that can be set on scales themselves. Each of these settings are functions that take scales as arguments and return the modified scales as results. The below image is a fairly uninformative plot, but serves to illustrate some of the settings available.
.qp.go[400;300]
.qp.point[([]x: .st.gen.normal 1000; y: 50+.st.gen.normal 1000; z: 1000?`a`b`c); `x; `y]
.qp.s.aes[`fill; `z] ,
.qp.s.scale[`fill; .gg.scale.colour.cat .gg.colour.brewer[`Set1;3]] ,
.qp.s.scale[`x;
// set the breaks (ticks) on the x axis
.gg.scale.breaks[0.01 0.5 1 2]
// on a log x axis
.gg.scale.log] ,
.qp.s.scale[`y;
// format the breaks to include a "$"
.gg.scale.format[{"$",string x}]
// set the breaks for the y axis
.gg.scale.breaks[48 50 52]
// set the max and min value of the y axis
.gg.scale.limits[45 55]
// on a power2 y axis
.gg.scale.power 2]
.gg.scale.alpha
Return an alpha (opacity) scale between the min and max alpha arguments. Note - alpha scales can only map numeric variables. An error will be thrown if a categorical variable is given.
Parameters:
Name | Type | Description |
---|---|---|
minAlpha | long | between 0 and 255 |
maxAlpha | long | between 0 and 255 |
Returns:
Type | Description |
---|---|
dict | scale |
Example: A scale from 50 to 255 (max) opacity
.gg.scale.alpha[50;255]
.gg.scale.apply
Apply a scale to a vector of data
Parameters:
Name | Type | Description |
---|---|---|
s | dict | scale |
v | any[] | data |
Returns:
Type | Description |
---|---|
any[] | scaled data |
See Also: .gg.scale.init
.gg.scale.categorical
Create a scale for a categorical variable (any data type). If given a numeric variable, the distinct numbers will be treated as independent categories, and will be evenly spaced along the axis. See .gg.scale.linear for a linear numeric scale.
The scale can optionally be initialized with a sorting function. This
function can reorder the categories so they display in any given order. By
default, the categories are sorted ascending. For default sorting behaviour,
provide no argument: .gg.scale.categorical[]
.
Note - the sort function is a function from the domain to the ordered domain. Elements can be injected or removed. Whatever is returned from the function will be displayed on the scale. To restrict a specific order to only the visible records, intersect the specific order with the domain as in the last example below. This allows drilldown to maintain the ordering while only displaying visible categories.
Returns:
Type | Description |
---|---|
dict | scale |
See Also: .gg.scale.linear
Example: Default ascending categorical scale
.gg.scale.categorical[]
Example: Descending categorical scale
.gg.scale.categorical[desc]
Example: Specific ordering in categorical scale
.gg.scale.categorical[{`IF`VVS1`VVS2`VS1`VS2`SI1`SI2`I1 inter x}]
.gg.scale.circle.area
Create a circle area scale, scaling to areas between the given max and min. This scale is a good candidate for coupling with a size aesthetic mapping on a point geometry.
Parameters:
Name | Type | Description |
---|---|---|
m | long | min area |
M | long | max area |
See Also: .gg.scale.circle.radius .qp.point .qp.s.aes
Example: Circle area scale
.gg.scale.circle.area[5;50]
.gg.scale.circle.radius
Create a circle radius scale, scaling to radii between the given max and min.
This scale is a good candidate for coupling with a size aesthetic mapping on a
point geometry, however, the points will grow quicker than their underlying value.
For a linear growth, see .gg.scale.circle.area
.
Parameters:
Name | Type | Description |
---|---|---|
m | long | min area |
M | long | max area |
See Also: .gg.scale.circle.area .qp.point .qp.s.aes
Example: Circle area scale
.gg.scale.circle.radius[2;6]
.gg.scale.colour.cat
Create a new categorical color scale using the list of colours given. If there are more values in the list than colours given, then the colours will wrap to include all values (note, values will not have unique colors if this is the case).
For example:
.gg.scale.colour.cat `green`red
// or
.gg.scale.colour.cat (.gg.colour.Green; .gg.colour.Red)
// or
.gg.scale.colour.cat `blues
to use a named colour palette
Alternatively, a dictionary of categories to colours can be provided
to make the colour mapping explicit. For example, if there are two
categories in the domain: `pass`fail
, we can assign `pass
to
green and `fail
to red with:
.gg.scale.colour.cat `pass`fail!(.gg.colour.Green; .gg.colour.Red)
See .gg.colour.COLOURS for available colours.
Parameter:
Name | Type | Description |
---|---|---|
colours | byte[][] | list of colours (0xrrggbb) |
Returns:
Type | Description |
---|---|
dict | categorical colour scale |
Example: Colour scale with 3 built-in colours
.gg.scale.colour.cat (.gg.colour.SteelBlue; .gg.colour.FireBrick; .gg.colour.Green)
Example: Colour scale with 3 built-in colours by symbol
.gg.scale.colour.cat `steelblue`firebrick`green
Example: Colour scale with 4 RGB colours
.gg.scale.colour.cat (0x336699; 0x669933; 0x993366; 0x558899)
Example: Colour scale with 4 RGB colours and explicit mapping
.gg.scale.colour.cat `a`b`c`d!(0x336699; 0x669933; 0x993366; 0x558899)
Example: Colour scale using a best-effort number of red colours from the Reds palette
.gg.scale.colour.cat `reds
.gg.scale.colour.cat10
Create a new 10-valued categorical color scale. If there are more than 10 distinct values in the list, then the colours will wrap to include all values (note, values will not have unique colors if this is the case).
Returns:
Type | Description |
---|---|
dict | categorical colour scale |
See Also: .gg.scale.colour.cat .gg.scale.colour.cat20
Example: 10-valued categorical colour scale applied to a geometry
t:([]x:til 10; y:1);
.qp.bar[t; `x; `y] (::)
.qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.cat10]
, .qp.s.scale[`y; .gg.scale.limits[0 1] .gg.scale.linear]
, .qp.s.geom[enlist[`gap]!enlist 0]
.gg.scale.colour.cat20
Create a new 20-valued categorical color scale. If there are more than 20 distinct values in the list, then the colours will wrap to include all values (note, values will not have unique colors if this is the case).
Returns:
Type | Description |
---|---|
dict | categorical colour scale |
See Also: .gg.scale.colour.cat .gg.scale.colour.cat10
Example: 20-valued categorical colour scale applied to a geometry
t:([]x:til 20; y:1);
.qp.bar[t; `x; `y] (::)
.qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.cat20]
, .qp.s.scale[`y; .gg.scale.limits[0 1] .gg.scale.linear]
, .qp.s.geom[enlist[`gap]!enlist 0]
.gg.scale.colour.gradient
Create a gradient scale between the two given colours. Expects numeric/interval data rather than categorical.
For a categorical color scale, see cat10, cat20, etc.
For a 3-valued gradient scale, see gradient2.
Parameters:
Name | Type | Description |
---|---|---|
minFill | byte[] | colour representing the min value (0xrrggbb) |
maxFill | byte[] | colour representing the max value (0xrrggbb) |
Returns:
Type | Description |
---|---|
dict | gradient scale |
Throws:
Type | Description |
---|---|
"scale+gradient error: x" |
See Also: .gg.scale.colour.cat .gg.scale.colour.cat10 .gg.scale.colour.cat20 .gg.scale.colour.gradient2
Example: Gradient scale between two built-in colours
t:([]x:til 500; y:1);
.qp.bar[t; `x; `y]
.qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.gradient[`steelblue; `firebrick]]
, .qp.s.scale[`y; .gg.scale.limits[0 1] .gg.scale.linear]
Example: Gradient scale between two built-in colours
.qp.bar[t; `x; `y]
.qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.gradient[`black; `white]]
, .qp.s.scale[`y; .gg.scale.limits[0 1] .gg.scale.linear]
Example: Gradient scale between two RGB colours
.qp.bar[t; `x; `y]
.qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.gradient[0x336699; 0x993366]]
, .qp.s.scale[`y; .gg.scale.limits[0 1] .gg.scale.linear]
.gg.scale.colour.gradient2
Create a gradient scale between the three given colours, with a specified midpoint value. Expects numeric/interval data rather than categorical. For a categorical color scale, see cat10, cat20, etc.
Parameters:
Name | Type | Description |
---|---|---|
midpoint | any | number representing the middle of the gradient (for centering). If null, mid point of data will be used. |
minFill | byte[] | colour representing the min value (0xrrggbb) |
middleFill | byte[] | colour representing the min value (0xrrggbb) |
maxFill | byte[] | colour representing the max value (0xrrggbb) |
Returns:
Type | Description |
---|---|
dict | gradient scale |
See Also: .gg.scale.colour.cat .gg.scale.colour.cat10 .gg.scale.colour.cat20 .gg.scale.colour.gradient
Example: Gradient scale between two built-in colours
t:([]x:til 500; y:1);
.qp.bar[t; `x; `y]
.qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.gradient2[250;
`steelblue; `white; `firebrick]]
, .qp.s.scale[`y; .gg.scale.limits[0 1] .gg.scale.linear]
Example: Gradient scale between two built-in colours
.qp.bar[t; `x; `y]
.qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.gradient2[360;
`steelblue; `white; `firebrick]]
, .qp.s.scale[`y; .gg.scale.limits[0 1] .gg.scale.linear]
Example: Gradient scale between two RGB colours
.qp.bar[t; `x; `y]
.qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.gradient2[120;
0x336699; 0x993366; 0x669933]]
, .qp.s.scale[`y; .gg.scale.limits[0 1] .gg.scale.linear]
.gg.scale.colour.gradientN
Create a gradient scale between any number of colours, with a specified midpoint value. Expects numeric/interval data rather than categorical. For a categorical color scale, see cat10, cat20, etc.
Parameters:
Name | Type | Description |
---|---|---|
midpoints | any | null | scale values for each intermediate gradient color between the extremes |
fill | byte[][] | colours representing the gradient step (0xrrggbb) |
Returns:
Type | Description |
---|---|
dict | gradient scale |
See Also: .gg.scale.colour.cat .gg.scale.colour.cat10 .gg.scale.colour.cat20 .gg.scale.colour.gradient .gg.scale.colour.gradient2
Example: Gradient scale between two built-in colours
t:([]x:til 500; y:1);
.qp.bar[t; `x; `y]
.qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.gradientN[250;
`steelblue`white`firebrick]]
, .qp.s.scale[`y; .gg.scale.limits[0 1] .gg.scale.linear]
Example: Gradient scale between two built-in colours
.qp.bar[t; `x; `y]
.qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.gradientN[360;
`steelblue`white`firebrick]]
, .qp.s.scale[`y; .gg.scale.limits[0 1] .gg.scale.linear]
Example: Gradient scale between two RGB colours
.qp.bar[t; `x; `y]
.qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.gradientN[120;
(0x336699; 0x993366; 0x669933)]]
, .qp.s.scale[`y; .gg.scale.limits[0 1] .gg.scale.linear]
Example: Gradient scale between several RGB colours
.qp.bar[t; `x; `y]
.qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.gradientN[::;
reverse `red`orange`yellow`lightgreen`teal`blue]]
, .qp.s.scale[`y; .gg.scale.limits[0 1] .gg.scale.linear]
Example: Rainbow gradient
.qp.bar[t; `x; `y]
.qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.gradientN[::;
reverse `red`orange`yellow`green`blue`indigo`violet]]
, .qp.s.scale[`y; .gg.scale.limits[0 1] .gg.scale.linear]
.gg.scale.compose
Compose takes two scales f and g and returns a new scale of the composition f . g
Parameters:
Name | Type | Description |
---|---|---|
f | dict | f scale |
g | dict | g scale |
Returns:
Type | Description |
---|---|
dict | scale of f . g |
Example: A log log scale
.gg.scale.compose[.gg.scale.log; .gg.scale.log]
Example: A log fill scale
.gg.scale.compose[.gg.scale.colour.cat10; .gg.scale.log]
.gg.scale.date
Positional scale for date variables
.gg.scale.datetime
Positional scale for datetime variables
.gg.scale.fromMeta
Return a scale for a column based on a tables meta type
Parameters:
Name | Type | Description |
---|---|---|
collapse | boolean | whether compound values should be collapsed (e.g., for a polygon chart) |
typec | char | meta type character |
Returns:
Type | Description |
---|---|
dict | scale |
Example:
.gg.scale.fromMeta "j"
.gg.scale.init
Initialize a scale on provided data
Parameters:
Name | Type | Description |
---|---|---|
s | dict | scale |
v | any[] | data |
Returns:
Type | Description |
---|---|
dict | initialized scale |
Throws:
Type | Description |
---|---|
validation errors |
Example:
.gg.scale.init[.gg.scale.linear] til 1000
.gg.scale.line.size
Create a scale for the strokewidth of a line.
Parameters:
Name | Type | Description |
---|---|---|
m | long | min line size |
M | long | max line size |
Returns:
Type | Description |
---|---|
dict | line size scale |
Example:
.gg.scale.line.size[1;10]
.gg.scale.linear
Positional linear scale for numeric variables
.gg.scale.log
Positional logarithmic scale for numeric variables
.gg.scale.mercator
Create a Mercator scale. Useful for geo data.
Parameter:
Name | Type | Description |
---|---|---|
isLat | boolean | Whether the applied data is latitude |
Returns:
Type | Description |
---|---|
dict | a Mercator scale |
Example: Longitude scale
.gg.scale.mercator[0b]
Example: Latitude scale
.gg.scale.mercator[1b]
.gg.scale.minute
Positional scale for minute variables
.gg.scale.month
Positional scale for month variables
.gg.scale.power
Create a power scale. Each value will be raised to the given power.
Parameter:
Name | Type | Description |
---|---|---|
e | number | exponent for the power |
Returns:
Type | Description |
---|---|
dict | power scale |
Example: A power(2) scale
.gg.scale.power[2]
Example: A square root scale
.gg.scale.power[0.5]
.gg.scale.second
Positional scale for second variables
.gg.scale.square
Given an X or Y scale, ensure that the other (X or Y) scale has the same range (useful for maps).
Note - Only one of the scales needs to be marked square for this effect.
Parameter:
Name | Type | Description |
---|---|---|
sc | dict |
Returns:
Type | Description |
---|---|
dict |
Example: Square longitude scale
.gg.scale.square .gg.scale.mercator[0b]
.gg.scale.time
Positional scale for time variables
.gg.scale.timespan
Positional scale for timespan variables
.gg.scale.timestamp
Positional scale for timestamp variables
.gg.scale.weekday
Positional scale for timestamp/datetime data to be displayed as a categorical weekday value label validate