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)

Parameter(s):

Name Type Description
item symbol name of the aesthetic
col symbol value for the aesthetic

Returns:

Name Type Description
<returns> 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]

Image

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]

Image

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]

Image

.qp.s.aggr

Create a new aggregation setting.

Applies only to Histogram, HHistogram, and Heatmap plots.

Parameter(s):

Name Type Description
aggr any value for the aesthetic

Returns:

Name Type Description
<returns> 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]

Image

.qp.s.binx

Create a new x bin setting.

Applies only to Histogram, HHistogram, and Heatmap plots.

Parameter(s):

Name Type Description
d symbol width or count w orc
s number width or count arg
p null | number padding (normally 0)

Returns:

Name Type Description
<returns> 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]

Image

.qp.s.biny

Create a new y bin setting.

Applies only to Histogram, HHistogram, and Heatmap plots.

Parameter(s):

Name Type Description
d symbol width or count w orc
s number width or count arg
p null | number padding (normally 0)

Returns:

Name Type Description
<returns> 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]

Image

.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(s):

Name Type Description
col symbol value for the aesthetic

Returns:

Name Type Description
<returns> 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]

Image

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.polar]

Image

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]

Image

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]

Image

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]

Image

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!(.gg.colour.FireBrick; 2)]

Image

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]

Image

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]

Image

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.breaks[()] .gg.scale.limits[0 0N] .gg.scale.linear]
          , .qp.s.scale[`y; .gg.scale.limits[0 0] .gg.scale.linear]

Image

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.breaks[()] .gg.scale.limits[0 0N] .gg.scale.linear]
          , .qp.s.scale[`y; .gg.scale.limits[0 0] .gg.scale.linear]

Image

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.breaks[()] .gg.scale.limits[0 0N] .gg.scale.linear]
          , .qp.s.scale[`x; .gg.scale.limits[0 0] .gg.scale.linear]

Image

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.breaks[()] .gg.scale.limits[0 0N] .gg.scale.linear]
          , .qp.s.scale[`x; .gg.scale.limits[0 0] .gg.scale.linear]

Image

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; .gg.colour.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]

Image

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; .gg.colour.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]

Image

.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(s):

Name Type Description
g dict dictionary of geom properties to set, and their corresponding values

Returns:

Name Type Description
<returns> 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[enlist[`fill]!enlist .gg.colour.FireBrick]

Image

Example:

 .qp.point[t; `x; `y]
     .qp.s.geom[`size`alpha`colour`strokewidth!(6; 0x00; .gg.colour.SteelBlue; 2)]

Image

.qp.s.init

.qp.s.labels

Create a new label setting.

Parameter(s):

Name Type Description
l any value for the aesthetic

Returns:

Name Type Description
<returns> 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 ($)")]

Image

.qp.s.legend

Create a new custom legend setting.

Parameter(s):

Name Type Description
title string | symbol value for the aesthetic
legend dict Dictionary of symbols to colours

Returns:

Name Type Description
<returns> 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; .gg.colour.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; .gg.colour.SteelBlue)];

         .qp.point[([]x: 20?500; y: 20?500); `x; `y]
             .qp.s.geom[`size`fill!(3; .gg.colour.Purple)])

Image

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(s):

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])

Image

.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(s):

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; ::]

Image

Example: Heatmap normalizing the Y column

     .qp.heatmap[t; `x; `y]
          .qp.s.norm[`y]

Image

.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(s):

Name Type Description
f fn (table) → table Handler taking the subset of the layer's data that would be displayed

Returns:

Name Type Description
<returns> 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.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(s):

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])

Image

.qp.s.scale

Create a new scale setting. See .gg.scale for available Positional and Aesthetic scales.

Parameter(s):

Name Type Description
item symbol name of the aesthetic
col symbol value for the aesthetic

Returns:

Name Type Description
<returns> 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[.gg.colour.FireBrick; .gg.colour.SteelBlue]]

Image

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 (.gg.colour.FireBrick; .gg.colour.SeaGreen; .gg.colour.SteelBlue)]

Image

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!(
              .gg.colour.FireBrick; .gg.colour.SeaGreen; .gg.colour.SteelBlue)]

Image

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]

Image

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.i.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 .gg.colour.brewer[`Blues;6]];   

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]

Image

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]]

Image

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]

Image

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]

Image

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]

Image

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]