Layer settings
.qp.s.aes
Create a new aesthetic mapping (mapping a variable in the data to a visual property).
The properties that can be mapped are different depending on the geometry used (see .gg.cheat.sheet[]
for a list of
geometries and their properties). In general, geometries can support the following properties:
`x
- X position`y
- Y position`fill
- Fill colour`alpha
- Opacity`colour
- Outline colour`strokewidth
- Outline size`group
- Grouping (combined with`position
geom settings)
Parameters:
Name | Type | Description |
---|---|---|
item | symbol | name of the aesthetic |
col | symbol | value for the aesthetic |
Returns:
Type | Description |
---|---|
dict |
Example: Add a fill aesthetic;
t: ([] x: 5*til 10; y: 5*-10?10; z:10?`a`b );
.qp.point[t; `x; `x]
.qp.s.aes[`fill; `x]
Example: Add multiple aesthetics
t: ([] x: 5*til 10; y: 5*-10?10; z:10?`a`b );
.qp.point[t; `x; `y]
.qp.s.aes[`fill; `x] ,
.qp.s.aes[`alpha; `y] ,
.qp.s.aes[`size; `y]
Example: Add multiple aesthetics using a single call
t: ([] x: 5*til 10; y: 5*-10?10; z:10?`a`b );
.qp.point[t; `x; `y]
.qp.s.aes[`fill`alpha`size; `x`y`y]
.qp.s.aggr
Create a new aggregation setting.
Applies only to Histogram, HHistogram, and Heatmap plots.
Parameter:
Name | Type | Description |
---|---|---|
aggr | any | value for the aesthetic |
Returns:
Type | Description |
---|---|
dict |
Example: Add a count and custom aggregation (avg
of y
)
.qp.histogram[([]x:til 45; y:til 45); `x]
.qp.s.aggr[.st.a.count[] , .st.a.custom[`yout; `y; avg]]
,.qp.s.aes[`fill; `yout]
.qp.s.binx
Create a new x bin setting.
Applies only to Histogram, HHistogram, and Heatmap plots.
Parameters:
Name | Type | Description |
---|---|---|
d | symbol | width or count w or c |
s | number | width or count arg |
p | null | number | padding (normally 0) |
Returns:
Type | Description |
---|---|
dict |
Example: Change x bin settings to count=100
.qp.heatmap[([]x:500?450; y:500?450); `x; `y]
.qp.s.binx[`c; 100; 0]
.qp.s.biny
Create a new y bin setting.
Applies only to Histogram, HHistogram, and Heatmap plots.
Parameters:
Name | Type | Description |
---|---|---|
d | symbol | width or count w or c |
s | number | width or count arg |
p | null | number | padding (normally 0) |
Returns:
Type | Description |
---|---|
dict |
Example: Change y bin settings to count=100
.qp.heatmap[([]x:500?450; y:500?450); `x; `y]
.qp.s.biny[`c; 100; 0]
.qp.s.coord
Change the coordinate system setting.
Supported coordinate systems are:
.gg.coords.rect
- rectangular/2D Cartesian coordinates.gg.coords.polar
- polar coordinates.gg.coords.cube
- cubic/3D Cartesian coordinates
By default, rectangular coordinates are assumed for 2D plots, and cubic coordinates for 3D plots.
Note - if polar coordinates are used, the frame canvas can be locked to
a circle by specifying `square
as the `aspect_ratio
in the
theme. Otherwise the frame canvas will fill the space available. See
the examples below.
Parameter:
Name | Type | Description |
---|---|---|
col | symbol | value for the aesthetic |
Returns:
Type | Description |
---|---|
dict |
Example: Basic point plot (default is rectangular coordinates)
.qp.point[([]x:45?45; y:45?45); `x; `y]
.qp.s.coord[.gg.coords.rect]
Example: Explicit rectangular coordinates
.qp.theme[enlist[`aspect_ratio]!enlist `square]
.qp.point[([]x:45?45; y:45?45); `x; `y]
.qp.s.coord[.gg.coords.rect]
Example: Custom rectangular coordinates plot
.qp.bar[([]x:`a`b`c`d`e; y:9 6 4 3 1); `x; `y]
.qp.s.coord[.gg.coords.rect]
, .qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.cat10]
, .qp.s.scale[`y; .gg.scale.limits[0 9] .gg.scale.linear]
Example: Custom cubic coordinates plot
.qp.point3D[([]x:45?45; y:45?45; z:45?45); `x; `y; `z]
.qp.s.coord[.gg.coords.cube . 2#4*atan[1]%3]
Example: Change the coordinate system to polar
.qp.theme[enlist[`aspect_ratio]!enlist `square]
.qp.bar[([]x:`a`b`c`d`e; y:9 6 4 3 1); `x; `y]
.qp.s.coord[.gg.coords.polar]
, .qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.cat10]
, .qp.s.scale[`y; .gg.scale.limits[0 9] .gg.scale.linear]
Example: The interpolation for polar coordinate can be changed
// Use .gg.coords.polarn[n] to have lines from a->b with no interpolation
.qp.segment[([]x1:45#0; y1:45#0; x2: 45?45; y2: 45?45); `x1; `y1; `x2; `y2]
.qp.s.coord[.gg.coords.polarn 2]
, .qp.s.geom[`fill`size!(`firebrick; 2)]
Example: Change geometry to horizontal bars, rect coords
.qp.hbar[([]x:`a`b`c`d`e; y:9 6 4 3 1); `y; `x]
.qp.s.coord[.gg.coords.rect]
, .qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.cat10]
, .qp.s.scale[`x; .gg.scale.limits[0 9] .gg.scale.linear]
Example: Change coordinate system to polar
.qp.theme[enlist[`aspect_ratio]!enlist `square]
.qp.hbar[([]x:`a`b`c`d`e; y:9 6 4 3 1); `y; `x]
.qp.s.coord[.gg.coords.polar]
, .qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.cat10]
, .qp.s.scale[`x; .gg.scale.limits[0 9] .gg.scale.linear]
Example: Customize limits, rect coordinates
.qp.hbar[([]z:0; x:`a`b`c`d`e; y:9 6 4 3 1); `y; `z]
.qp.s.coord[.gg.coords.rect]
, .qp.s.aes[`group; `x]
, .qp.s.geom[`gap`position!(0; `stack)]
, .qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.cat10]
, .qp.s.scale[`x; .gg.scale.extend[0b] .gg.scale.breaks[()] .gg.scale.limits[0 0N] .gg.scale.linear]
, .qp.s.scale[`y; .gg.scale.limits[0 0] .gg.scale.linear]
Example: Change coordinate system to polar
.qp.theme[enlist[`aspect_ratio]!enlist `square]
.qp.hbar[([]z:0; x:`a`b`c`d`e; y:9 6 4 3 1); `y; `z]
.qp.s.coord[.gg.coords.polar]
, .qp.s.aes[`group; `x]
, .qp.s.geom[`gap`position!(0;`stack)]
, .qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.cat10]
, .qp.s.scale[`x; .gg.scale.extend[0b] .gg.scale.breaks[()] .gg.scale.limits[0 0N] .gg.scale.linear]
, .qp.s.scale[`y; .gg.scale.limits[0 0] .gg.scale.linear]
Example: Change geometry to vertical bars, rect coordinates
.qp.bar[([]z:0; x:`a`b`c`d`e; y:9 6 4 3 1); `z; `y]
.qp.s.coord[.gg.coords.rect]
, .qp.s.aes[`group; `x]
, .qp.s.geom[`gap`position!(0; `stack)]
, .qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.cat10]
, .qp.s.scale[`y; .gg.scale.extend[0b] .gg.scale.breaks[()] .gg.scale.limits[0 0N] .gg.scale.linear]
, .qp.s.scale[`x; .gg.scale.limits[0 0] .gg.scale.linear]
Example: Change coordinate system to polar
.qp.theme[enlist[`aspect_ratio]!enlist `square]
.qp.bar[([]z:0; x:`a`b`c`d`e; y:9 6 4 3 1); `z; `y]
.qp.s.coord[.gg.coords.polar]
, .qp.s.aes[`group; `x]
, .qp.s.geom[`gap`position!(0; `stack)]
, .qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.cat10]
, .qp.s.scale[`y; .gg.scale.extend[0b] .gg.scale.breaks[()] .gg.scale.limits[0 0N] .gg.scale.linear]
, .qp.s.scale[`x; .gg.scale.limits[0 0] .gg.scale.linear]
Example: Polar coordinates are useful to visualize tree leaves
// Generate a binary tree of height 8
h: 8;
n: sum pn:"j"$xexp[2;]til h;
ls: n?`8;
ps: `,(,/)2#'(count[ls]-"j"$2 xexp h - 1)#ls;
t: ([]parent: ps; label: ls; amount: n?50);
// Custom layout algorithm
arrange : {[table; level; a; p; o]
ra: select from table where parent = p;
ra[`amount]: ra[`amount] % sum ra`amount;
ra : `amount xdesc ra;
if [0 = count ra;
: ra];
t: ([] parent: p;
x1: "f"$o+0,sums a*-1_ra`amount;
w: a*ra`amount;
y1: level;
y2: level + 1;
label: ra`label);
t[`x2]: t[`x1] + t[`w];
: t , raze .z.s[table; level + 1]'[t`w; ra`label; t`x1];
};
.qp.theme[`aspect_ratio`legend_use!(`square; 0b)]
.qp.rect[arrange[t; 0f; 1; `; 0f]; `y1; `x1; `y2; `x2]
.qp.s.geom[`alpha`colour!(0xb0; `white)]
, .qp.s.aes[`fill; `parent]
, .qp.s.scale[`y; .gg.scale.extend[0b] .gg.scale.linear]
, .qp.s.scale[`x; .gg.scale.extension[0.3] .gg.scale.linear]
, .qp.s.scale[`fill; .gg.scale.colour.cat20]
Example: Sunburst chart
.qp.theme[`aspect_ratio`legend_use!(`square; 0b)]
.qp.rect[arrange[t; 0f; 1; `; 0f]; `y1; `x1; `y2; `x2]
.qp.s.geom[`alpha`colour!(0xb0; `white)]
, .qp.s.coord[.gg.coords.polar]
, .qp.s.aes[`fill; `parent]
, .qp.s.scale[`y; .gg.scale.extend[0b] .gg.scale.linear]
, .qp.s.scale[`x; .gg.scale.extension[0.3] .gg.scale.linear]
, .qp.s.scale[`fill; .gg.scale.colour.cat20]
.qp.s.geom
Create a new geometry setting.
The properties that can be mapped are different depending on the geometry used (see .gg.cheat.sheet[]
for a list of
geometries and their properties). In general, geometries can support the following properties:
`fill
- Fill colour`alpha
- Opacity`colour
- Outline colour`strokewidth
- Outline size`position
- position adjust (`dodge
, or`stack
where supported, combined with`group
aes setting)
Other geometries may have custom properties that can be mapped as well (for example `width
and `height
in some cases).
Parameter:
Name | Type | Description |
---|---|---|
g | dict | dictionary of geom properties to set, and their corresponding values |
Returns:
Type | Description |
---|---|
dict |
Example:
t : ([]x:sums?[45?1.<0.5;-1;1]; y:sums?[45?1.<0.5;-1;1]);
.qp.point[t; `x; `y]
.qp.s.geom[``fill!(::;`firebrick)]
Example:
.qp.point[t; `x; `y]
.qp.s.geom[`size`alpha`colour`strokewidth!(6; 0x00; `steelblue; 2)]
.qp.s.init
.qp.s.labels
Create a new label setting.
Parameter:
Name | Type | Description |
---|---|---|
l | any | value for the aesthetic |
Returns:
Type | Description |
---|---|
dict |
Example:
t: ([]x: 500?500; y: 500?500);
.qp.point[t; `x; `y]
.qp.s.scale[`y; .gg.scale.log]
, .qp.s.labels[`x`y!("X Position";"log of Y ($)")]
.qp.s.legend
Create a new custom legend setting.
Parameters:
Name | Type | Description |
---|---|---|
title | string | symbol | value for the aesthetic |
legend | dict | Dictionary of symbols to colours |
Returns:
Type | Description |
---|---|
dict |
Example: Reference static colours from independent layers in a single legend
.qp.stack (
.qp.point[([]x: 20?500; y: 20?500); `x; `y]
.qp.s.geom[`size`fill!(3; `firebrick)]
, .qp.s.legend["My legend"; `a`b`c!.gg.colour`firebrick`steelblue`purple];
.qp.point[([]x: 20?500; y: 20?500); `x; `y]
.qp.s.geom[`size`fill!(3; `steelblue)];
.qp.point[([]x: 20?500; y: 20?500); `x; `y]
.qp.s.geom[`size`fill!(3; `purple)])
.qp.s.link
Add a link dependency.
A link between plots (in a separate frame) ensures that whenever either of the plots is zoomed (drilled into), all other "linked" layers will inherit the new data of the zoomed layer. This way all linked plots are kept in sync.
Many layer may be linked to the same ID as long as all layers are in separate
independent frames. For dependencies within a single frame, see .qp.s.primary
.
Parameter:
Name | Type | Description |
---|---|---|
linkid | symbol | a unique symbol relating to the dependency group |
See Also: .qp.s.primary .qp.s.secondary
Example:
t : ([] x:sums?[45?1.<0.5;-1;1]; y:sums?[45?1.<0.5;-1;1]; z:45?45);
.qp.layout[`hori; ::] (
.qp.point[t; `x; `y]
.qp.s.link[`myid];
.qp.point[t; `x; `z]
.qp.s.link[`myid])
.qp.s.norm
Normalize one of the axes of a heatmap. For example, if the y column is normalized, each row of the heatmap will have a minimum and maximum value -- no row will be affected by any other row.
Parameter:
Name | Type | Description |
---|---|---|
col | symbol | the column to normalize |
Example: Heatmap without normalization
t : ([]x:500?45; y:500?5?`5);
.qp.heatmap[t; `x; `y; ::]
Example: Heatmap normalizing the y column
.qp.heatmap[t; `x; `y]
.qp.s.norm[`y]
.qp.s.onclick
Add a click handler or tooltip data formatter to a layer
Return anything other than a table (eg, 0b
) to disable tooltips for the layer
Parameter:
Name | Type | Description |
---|---|---|
f | fn (table) → table | Handler taking the subset of the layer's data that would be displayed |
Returns:
Type | Description |
---|---|
table | table to display |
Example: Choose which columns should appear in the results
.qp.point[([]x:til 45;y:til 45;z:til 45); `x;`y]
.qp.s.onclick[{ `x`y#x }]
Example: Fire a new visual based on the clicked data
.qp.point[([]x:til 45;y:til 45;z:til 45); `x;`y]
.qp.s.onclick[{ .qp.managed[`tooltip;500;500] .qp.point[x;`x;`y;::]; x }]
.qp.s.ondrilldown
Add a zoom handler to a layer
Parameter:
Name | Type | Description |
---|---|---|
f | fn (table) → table |
Returns:
Type | Description |
---|---|
null |
.qp.s.primary
Register the layer as a primary data supplier for the frame. Whenever the frame is zoomed, the primary layer will feed its data to the secondary layer(s).
The primary layer and it's secondary layers must be within the same frame.
Parameter:
Name | Type | Description |
---|---|---|
id | symbol | unique identifier for the dependency group |
See Also: .qp.s.link .qp.s.secondary
Example:
t:([]date:til 100; price:sums?[100?1.<0.5;-1;1]);
.qp.stack (
.qp.point[t; `date; `price]
.qp.s.primary[`myid];
.qp.smooth[t; `date; `price; ::]
.qp.s.secondary[`myid])
.qp.s.scale
Create a new scale setting. See .gg.scale for available Positional and Aesthetic scales.
Parameters:
Name | Type | Description |
---|---|---|
item | symbol | name of the aesthetic |
col | symbol | value for the aesthetic |
Returns:
Type | Description |
---|---|
dict |
Example: Load data and add fill gradient scale
t: ([] x:til 20);
.qp.point[t; `x; `x]
.qp.s.geom[enlist[`size]!enlist 4]
, .qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.gradient[`firebrick; `steelblue]]
Example: Change to custom categorical fill scale
t: ([] x:til 20; y:20?`a`b`c);
.qp.point[t; `x; `x]
.qp.s.geom[enlist[`size]!enlist 4]
, .qp.s.aes[`fill; `y]
, .qp.s.scale[`fill; .gg.scale.colour.cat `firebrick`seagreen`steelblue]
Example: Change to custom categorical fill scale with explicit color mappings
.qp.point[t; `x; `x]
.qp.s.geom[enlist[`size]!enlist 4]
, .qp.s.aes[`fill; `y]
, .qp.s.scale[`fill; .gg.scale.colour.cat `b`c`a!`firebrick`seagreen`steelblue]
Example: Change to built-in categorical fill scale
t: ([] x:til 20);
.qp.point[t; `x; `x]
.qp.s.geom[enlist[`size]!enlist 4]
, .qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.cat20]
Example: Custom bucketed scale for continuous domain
// A simple table to display
t: ([]x:10000?1.;y:10000?1.);
// Add a continuous column to map to fill colour
t: update z: {.gg.proj.proj[(min x;max x);0 5000000;x]} sin[x]*sin[y] from t;
// Labels for the legend
labels: ("0-1M";"1-2M";"2-3M";"3-4M";"4-5M");
// Add a new column to represent the legend buckets and map this to the fill colour
t: update fillcol: labels("f"$1000000*til 5)?1000000 xbar z from t;
.qp.point[t; `x; `y]
.qp.s.aes[`fill; `fillcol]
// Map the fill aesthetic to the bucketed column
// Use a categorical scale for the now discrete values
, .qp.s.scale[`fill; .gg.scale.colour.cat `blues]
Example: Change y scale to log
t: ([] x:til 20);
.qp.point[t; `x; `x]
.qp.s.geom[enlist[`size]!enlist 4]
, .qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.cat20]
, .qp.s.scale[`y; .gg.scale.log]
Example: Change y scale to power[2]
t: ([] x:til 20);
.qp.point[t; `x; `x]
.qp.s.geom[enlist[`size]!enlist 4]
, .qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.cat20]
, .qp.s.scale[`y; .gg.scale.power[2]]
Example: Change limits on linear x scale
t: ([] x:til 20);
.qp.point[t; `x; `x]
.qp.s.geom[enlist[`size]!enlist 4]
, .qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.cat20]
, .qp.s.scale[`y; .gg.scale.power[2]]
, .qp.s.scale[`x; .gg.scale.limits [-5 25] .gg.scale.linear]
Example: Add axis padding (extension) on y axis
t: ([] x:til 20);
.qp.point[t; `x; `x]
.qp.s.geom[enlist[`size]!enlist 4]
, .qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.cat20]
, .qp.s.scale[`y; .gg.scale.extension[0.3] .gg.scale.power[2]]
, .qp.s.scale[`x; .gg.scale.limits [-5 25] .gg.scale.linear]
Example: Add explicit x axis breaks (ticks)
t: ([] x:til 20);
.qp.point[t; `x; `x]
.qp.s.geom[enlist[`size]!enlist 4]
, .qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.cat20]
, .qp.s.scale[`y; .gg.scale.extension[0.3] .gg.scale.power[2]]
, .qp.s.scale[`x; .gg.scale.breaks[0 10 20] .gg.scale.limits [-5 25] .gg.scale.linear]
Example: Add y scale breaks and custom format printer
.qp.point[t; `x; `x]
.qp.s.geom[enlist[`size]!enlist 4]
, .qp.s.aes[`fill; `x]
, .qp.s.scale[`fill; .gg.scale.colour.cat20]
, .qp.s.scale[`y; .gg.scale.format[{string[sqrt x],"^2"}] .gg.scale.breaks[0 4 9 16] .gg.scale.extension[0.3] .gg.scale.power[2]]
, .qp.s.scale[`x; .gg.scale.breaks[0 10 20] .gg.scale.limits [-5 25] .gg.scale.linear]
.qp.s.secondary
Register the layer as a secondary data supplier for the frame. Whenever the frame is zoomed, the primary layer will feed its data to the secondary layer(s).
The secondary layer must be in the same frame as the primary layer.
Parameter:
Name | Type | Description |
---|---|---|
id | symbol | unique identifier for the dependency group |
See Also: .qp.s.primary
Example:
t:([]date:til 100; price:sums?[100?1.<0.5;-1;1]);
.qp.stack (
.qp.point[t; `date; `price]
.qp.s.primary[`myid];
.qp.smooth[t; `date; `price; ::]
.qp.s.secondary[`myid])
.qp.s.share
Share a scale between plots in separate frames based on unique label. All plots with the same label/axis pair will contain the same limits when plotted or zoomed.
Parameters:
Name | Type | Description |
---|---|---|
label | symbol | unique label to associate plots to this shared scale |
scale | symbol | x or y - the axis to share |
Returns:
Type | Description |
---|---|
dict |
Example: Shared y scale between a heatmap and scatter
// Notice how the limits of both plots are extended
// to show the same region
.qp.horizontal (
.qp.heatmap[([]x:til 45); `x; `x]
.qp.s.share[`label; `y];
.qp.point[([]x:neg til 45); `x; `x]
.qp.s.share[`label; `y]
)
.qp.s.stat
Create a new statistical function setting for the layer. See .gg.stat for available statistical transform functions.
Parameter:
Name | Type | Description |
---|---|---|
val | any | statistical transform (see .gg.stat for options) |
Returns:
Type | Description |
---|---|
dict |
Example: A histogram is bar geometry with a 1D bin stat
t: ([]x: 500?5?`5);
.qp.bar[t; `x; `count__]
.qp.s.stat[.gg.stat.bin1d[`x; ::; .st.a.count[]; ::]]
.qp.s.textalign
Deprecated
Change the alignment of a text geometry.
Note, this setting is deprecated, and the
.qp.s.geom
setting on a text geometry should be used instead.
Parameter:
Name | Type | Description |
---|---|---|
val | symbol | one of `left`middle`right |
See Also: .qp.text
Example: The default is left alignment
t: ([]x:til 5; label:5?`8);
.qp.text[t; `x; `x; `label; ::]
Example: Explicit left alignment
.qp.text[t; `x; `x; `label]
.qp.s.textalign[`left]
Example: Middle alignment
.qp.text[t; `x; `x; `label]
.qp.s.textalign[`middle]
Example: Right alignment
.qp.text[t; `x; `x; `label]
.qp.s.textalign[`right]