---
product: "AG Studio"
title: "Scatter Charts"
description: "Build scatter and bubble charts in AG Studio to compare two numeric fields: which fields they need, legends, tooltips, point size and Format settings."
framework: react
version: "3.1.0"
related:
    - title: "Bar and Column Charts"
      url: "https://www.ag-grid.com/studio/analysts/bar-and-column-charts/"
    - title: "Line and Area Charts"
      url: "https://www.ag-grid.com/studio/analysts/line-and-area-charts/"
    - title: "Combo Charts"
      url: "https://www.ag-grid.com/studio/analysts/combo-charts/"
    - title: "Polar Charts"
      url: "https://www.ag-grid.com/studio/analysts/polar-charts/"
    - title: "Proportional Charts"
      url: "https://www.ag-grid.com/studio/analysts/proportional-charts/"
    - title: "Progression Charts"
      url: "https://www.ag-grid.com/studio/analysts/progression-charts/"
    - title: "Hierarchical Charts"
      url: "https://www.ag-grid.com/studio/analysts/hierarchical-charts/"
    - title: "Statistical Charts"
      url: "https://www.ag-grid.com/studio/analysts/statistical-charts/"
llms: "https://www.ag-grid.com/studio/llms.txt"
---

# Scatter Charts

Scatter Charts plot one point per item across two axes, so you can see how two numeric fields relate.

**Scatter Chart** plots dots on two axes to compare grouped data and show correlations.

**Bubble Chart** extends a scatter plot with variable dot sizes, adding a third data dimension.

The example below shows a Scatter Chart above a Bubble Chart, both plotting each store's floor area against its revenue and coloured by region. The Bubble Chart also sizes each store by its number of visitors. Store is in the Group By slot and Region is in the Legend slot.

#### Scatter Chart

```ts
import {
  AgReportState,
  AgStudioApi,
  AgStudioProperties,
  createStudio,
  enableStudioDevValidations,
} from "ag-studio";
import { getData } from "./data.ts";

if (process.env.NODE_ENV !== "production") {
  // Enable extended validations only for development
  enableStudioDevValidations();
}

const initialState: AgReportState = {
  pages: [
    {
      id: "page1",
      widgets: {
        "scatter-chart": {
          type: "scatter-chart",
          dataMapping: {
            groupByKey: [{ id: "stores.store" }],
            legendKey: [{ id: "stores.region" }],
            categoryKey: [{ id: "stores.floor_area", aggregation: "sum" }],
            valueKey: [{ id: "stores.revenue", aggregation: "sum" }],
            tooltipKey: [],
          },
          format: {
            title: {
              enabled: true,
              text: "Scatter Chart",
            },
            subtitle: {
              enabled: true,
              text: "Floor area against annual revenue, one point per store",
            },
            style: {
              theme: {
                common: {
                  legend: {
                    enabled: true,
                  },
                },
              },
            },
          },
        },
        "bubble-chart": {
          type: "bubble-chart",
          dataMapping: {
            groupByKey: [{ id: "stores.store" }],
            legendKey: [{ id: "stores.region" }],
            sizeKey: [{ id: "stores.visitors", aggregation: "sum" }],
            categoryKey: [{ id: "stores.floor_area", aggregation: "sum" }],
            valueKey: [{ id: "stores.revenue", aggregation: "sum" }],
            tooltipKey: [],
          },
          format: {
            title: {
              enabled: true,
              text: "Bubble Chart",
            },
            subtitle: {
              enabled: true,
              text: "Floor area against annual revenue, sized by yearly visitors",
            },
            style: {
              theme: {
                common: {
                  legend: {
                    enabled: true,
                  },
                },
              },
            },
          },
        },
      },
      widgetLayout: {
        "scatter-chart": {
          xTrack: 0,
          yTrack: 0,
          xSpan: 24,
          ySpan: 20,
        },
        "bubble-chart": {
          xTrack: 0,
          yTrack: 20,
          xSpan: 24,
          ySpan: 20,
        },
      },
    },
  ],
  selectedPageId: "page1",
  panels: {
    filters: {
      collapsed: true,
    },
    data: {
      collapsed: true,
    },
    edit: {
      collapsed: true,
    },
  },
};

const studioProperties: AgStudioProperties = {
  mode: "edit",
  initialState,
  data: getData(),
};

let studioApi: AgStudioApi;

// setup Studio after the page has finished loading
const studioDiv = document.querySelector<HTMLElement>("#myStudio")!;
studioApi = createStudio(studioDiv, studioProperties);
```

[Live example: Scatter Chart](https://www.ag-grid.com/studio/examples/scatter-charts/scatter-chart/typescript/)

## Setup

| Slot | Required | Accepts | What it does |
| --- | --- | --- | --- |
| Group By | Yes | One category | Plots one point for each value of the field, such as each store. |
| X Axis | Yes | One numeric field | Sets each point's horizontal position, from the field aggregated for its group. |
| Y Axis | Yes | One numeric field | Sets each point's vertical position, from the field aggregated for its group. |
| Size | Bubble Chart only | One numeric field | Sets each bubble's size, from the field aggregated for its group. |
| Legend | No | One category | Colours the points by the field's values, such as each store's region. |
| Tooltip | No | Any fields | Shows the fields in the tooltip without plotting them. |

### Legend

A Legend gives each value of a category its own series and colour. Without one, every point belongs to a single series, named after the Y Axis field.

The example below plots each store's floor area against its revenue. The left column has nothing in the Legend slot, so every point is one colour. The right column has Region in the Legend slot, so each region has its own colour. The top row is a Scatter Chart and the bottom row is a Bubble Chart.

#### Legend

```ts
import {
  AgReportState,
  AgStudioApi,
  AgStudioProperties,
  createStudio,
  enableStudioDevValidations,
} from "ag-studio";
import { getData } from "./data.ts";

if (process.env.NODE_ENV !== "production") {
  // Enable extended validations only for development
  enableStudioDevValidations();
}

const initialState: AgReportState = {
  pages: [
    {
      id: "page1",
      widgets: {
        "scatter-no-legend": {
          type: "scatter-chart",
          dataMapping: {
            groupByKey: [{ id: "stores.store" }],
            categoryKey: [{ id: "stores.floor_area", aggregation: "sum" }],
            valueKey: [{ id: "stores.revenue", aggregation: "sum" }],
            tooltipKey: [],
          },
          format: {
            title: {
              enabled: true,
              text: "Scatter: No Legend Field",
            },
            subtitle: {
              enabled: true,
              text: "Nothing in the Legend slot",
            },
            style: {
              theme: {
                common: {
                  legend: {
                    enabled: true,
                  },
                },
              },
            },
          },
        },
        "scatter-region": {
          type: "scatter-chart",
          dataMapping: {
            groupByKey: [{ id: "stores.store" }],
            legendKey: [{ id: "stores.region" }],
            categoryKey: [{ id: "stores.floor_area", aggregation: "sum" }],
            valueKey: [{ id: "stores.revenue", aggregation: "sum" }],
            tooltipKey: [],
          },
          format: {
            title: {
              enabled: true,
              text: "Scatter: Region in Legend",
            },
            subtitle: {
              enabled: true,
              text: "Region in the Legend slot",
            },
            style: {
              theme: {
                common: {
                  legend: {
                    enabled: true,
                  },
                },
              },
            },
          },
        },
        "bubble-no-legend": {
          type: "bubble-chart",
          dataMapping: {
            groupByKey: [{ id: "stores.store" }],
            sizeKey: [{ id: "stores.visitors", aggregation: "sum" }],
            categoryKey: [{ id: "stores.floor_area", aggregation: "sum" }],
            valueKey: [{ id: "stores.revenue", aggregation: "sum" }],
            tooltipKey: [],
          },
          format: {
            title: {
              enabled: true,
              text: "Bubble: No Legend Field",
            },
            subtitle: {
              enabled: true,
              text: "Nothing in the Legend slot",
            },
            style: {
              theme: {
                common: {
                  legend: {
                    enabled: true,
                  },
                },
              },
            },
          },
        },
        "bubble-region": {
          type: "bubble-chart",
          dataMapping: {
            groupByKey: [{ id: "stores.store" }],
            legendKey: [{ id: "stores.region" }],
            sizeKey: [{ id: "stores.visitors", aggregation: "sum" }],
            categoryKey: [{ id: "stores.floor_area", aggregation: "sum" }],
            valueKey: [{ id: "stores.revenue", aggregation: "sum" }],
            tooltipKey: [],
          },
          format: {
            title: {
              enabled: true,
              text: "Bubble: Region in Legend",
            },
            subtitle: {
              enabled: true,
              text: "Region in the Legend slot",
            },
            style: {
              theme: {
                common: {
                  legend: {
                    enabled: true,
                  },
                },
              },
            },
          },
        },
      },
      widgetLayout: {
        "scatter-no-legend": { xTrack: 0, yTrack: 0, xSpan: 12, ySpan: 22 },
        "scatter-region": { xTrack: 12, yTrack: 0, xSpan: 12, ySpan: 22 },
        "bubble-no-legend": { xTrack: 0, yTrack: 22, xSpan: 12, ySpan: 22 },
        "bubble-region": { xTrack: 12, yTrack: 22, xSpan: 12, ySpan: 22 },
      },
    },
  ],
  selectedPageId: "page1",
  panels: {
    filters: {
      collapsed: true,
    },
    data: {
      collapsed: true,
    },
    edit: {
      collapsed: true,
    },
  },
};

const studioProperties: AgStudioProperties = {
  mode: "edit",
  initialState,
  data: getData(),
};

let studioApi: AgStudioApi;

// setup Studio after the page has finished loading
const studioDiv = document.querySelector<HTMLElement>("#myStudio")!;
studioApi = createStudio(studioDiv, studioProperties);
```

[Live example: Legend](https://www.ag-grid.com/studio/examples/scatter-charts/scatter-legend/typescript/)

See [Group By Legend](https://www.ag-grid.com/studio/analysts/building-widgets/#group-by-legend) for more on how the points are split.

### Tooltip

Fields in the Tooltip slot appear in the tooltip when you hover over a point, but are not plotted. Use the slot for context that would clutter the chart, such as the number of staff at each store.

In the example below, each point is a store, and the Setup tab is open beside the chart. Hover over a point to see its Visitors and Staff, which are in the Tooltip slot.

#### Tooltip

```ts
import {
  AgReportState,
  AgStudioApi,
  AgStudioProperties,
  createStudio,
  enableStudioDevValidations,
} from "ag-studio";
import { getData } from "./data.ts";

if (process.env.NODE_ENV !== "production") {
  // Enable extended validations only for development
  enableStudioDevValidations();
}

const initialState: AgReportState = {
  pages: [
    {
      id: "page1",
      widgets: {
        "area-vs-revenue": {
          type: "scatter-chart",
          dataMapping: {
            groupByKey: [{ id: "stores.store" }],
            categoryKey: [{ id: "stores.floor_area", aggregation: "sum" }],
            valueKey: [{ id: "stores.revenue", aggregation: "sum" }],
            tooltipKey: [
              { id: "stores.visitors", aggregation: "sum" },
              { id: "stores.staff", aggregation: "sum" },
            ],
          },
          format: {
            title: {
              enabled: true,
              text: "Floor Area against Revenue",
            },
            style: {
              theme: {
                scatter: {
                  series: {
                    size: 14,
                  },
                },
              },
            },
          },
        },
      },
      widgetLayout: {
        "area-vs-revenue": { xTrack: 0, yTrack: 0, xSpan: 24, ySpan: 24 },
      },
      selection: { type: "widget", id: "area-vs-revenue" },
    },
  ],
  selectedPageId: "page1",
};

const studioProperties: AgStudioProperties = {
  mode: "edit",
  initialState,
  panels: {
    edit: {
      right: ["edit"],
    },
  },
  data: getData(),
};

let studioApi: AgStudioApi;

// setup Studio after the page has finished loading
const studioDiv = document.querySelector<HTMLElement>("#myStudio")!;
studioApi = createStudio(studioDiv, studioProperties);
```

[Live example: Tooltip](https://www.ag-grid.com/studio/examples/scatter-charts/scatter-tooltip/typescript/)

## Format

Scatter Charts have these settings of their own on the Format tab, beside the title, axis and appearance settings every chart has. Your developer can change the defaults shown.

| Setting | Where | Default | What it does |
| --- | --- | --- | --- |
| Legend | Elements | Off | Shows the legend. **Position** places it around the chart, at the bottom by default. |
| Markers | Elements | Circle, Size 7 | On a Scatter Chart, sets the shape and size of each point. |
| Markers | Elements | Circle, Min Size 7, Max Size 30 | On a Bubble Chart, sets the shape of each bubble and the smallest and largest size. |
| Data Labels | Elements | Off | Shows each point's Y Axis value. **Font** and **Color** change the label text. |

The example below changes one setting from its default in each chart, over the same data.

#### Format

```ts
import {
  AgReportState,
  AgStudioApi,
  AgStudioProperties,
  createStudio,
  enableStudioDevValidations,
} from "ag-studio";
import { getData } from "./data.ts";

if (process.env.NODE_ENV !== "production") {
  // Enable extended validations only for development
  enableStudioDevValidations();
}

const initialState: AgReportState = {
  pages: [
    {
      id: "page1",
      widgets: {
        "data-labels": {
          type: "scatter-chart",
          dataMapping: {
            groupByKey: [{ id: "stores.store" }],
            legendKey: [{ id: "stores.region" }],
            categoryKey: [{ id: "stores.floor_area", aggregation: "sum" }],
            valueKey: [{ id: "stores.revenue", aggregation: "sum" }],
            tooltipKey: [],
          },
          format: {
            title: {
              enabled: true,
              text: "Scatter: Data Labels",
            },
            subtitle: {
              enabled: true,
              text: "Elements > Data Labels on",
            },
            style: {
              theme: {
                scatter: {
                  series: {
                    label: {
                      enabled: true,
                    },
                  },
                },
                common: {
                  legend: {
                    enabled: true,
                  },
                },
              },
            },
          },
        },
        "scatter-markers": {
          type: "scatter-chart",
          dataMapping: {
            groupByKey: [{ id: "stores.store" }],
            legendKey: [{ id: "stores.region" }],
            categoryKey: [{ id: "stores.floor_area", aggregation: "sum" }],
            valueKey: [{ id: "stores.revenue", aggregation: "sum" }],
            tooltipKey: [],
          },
          format: {
            title: {
              enabled: true,
              text: "Scatter: Markers",
            },
            subtitle: {
              enabled: true,
              text: "Elements > Markers > Shape Diamond, Size 12",
            },
            style: {
              theme: {
                scatter: {
                  series: {
                    shape: "diamond",
                    size: 12,
                  },
                },
                common: {
                  legend: {
                    enabled: true,
                  },
                },
              },
            },
          },
        },
        "bubble-markers": {
          type: "bubble-chart",
          dataMapping: {
            groupByKey: [{ id: "stores.store" }],
            legendKey: [{ id: "stores.region" }],
            sizeKey: [{ id: "stores.visitors", aggregation: "sum" }],
            categoryKey: [{ id: "stores.floor_area", aggregation: "sum" }],
            valueKey: [{ id: "stores.revenue", aggregation: "sum" }],
            tooltipKey: [],
          },
          format: {
            title: {
              enabled: true,
              text: "Bubble: Markers",
            },
            subtitle: {
              enabled: true,
              text: "Elements > Markers > Min Size 4, Max Size 40",
            },
            style: {
              theme: {
                bubble: {
                  series: {
                    minSize: 4,
                    maxSize: 40,
                  },
                },
                common: {
                  legend: {
                    enabled: true,
                  },
                },
              },
            },
          },
        },
        "legend-position": {
          type: "scatter-chart",
          dataMapping: {
            groupByKey: [{ id: "stores.store" }],
            legendKey: [{ id: "stores.region" }],
            categoryKey: [{ id: "stores.floor_area", aggregation: "sum" }],
            valueKey: [{ id: "stores.revenue", aggregation: "sum" }],
            tooltipKey: [],
          },
          format: {
            title: {
              enabled: true,
              text: "Legend Position",
            },
            subtitle: {
              enabled: true,
              text: "Elements > Legend > Position Right",
            },
            style: {
              theme: {
                common: {
                  legend: {
                    enabled: true,
                    position: "right",
                  },
                },
              },
            },
          },
        },
      },
      widgetLayout: {
        "data-labels": { xTrack: 0, yTrack: 0, xSpan: 12, ySpan: 22 },
        "scatter-markers": { xTrack: 12, yTrack: 0, xSpan: 12, ySpan: 22 },
        "bubble-markers": { xTrack: 0, yTrack: 22, xSpan: 12, ySpan: 22 },
        "legend-position": { xTrack: 12, yTrack: 22, xSpan: 12, ySpan: 22 },
      },
    },
  ],
  selectedPageId: "page1",
  panels: {
    filters: {
      collapsed: true,
    },
    data: {
      collapsed: true,
    },
    edit: {
      collapsed: true,
    },
  },
};

const studioProperties: AgStudioProperties = {
  mode: "edit",
  initialState,
  data: getData(),
};

let studioApi: AgStudioApi;

// setup Studio after the page has finished loading
const studioDiv = document.querySelector<HTMLElement>("#myStudio")!;
studioApi = createStudio(studioDiv, studioProperties);
```

[Live example: Format](https://www.ag-grid.com/studio/examples/scatter-charts/scatter-format/typescript/)
