Loading...
The quantize scale is a discretization scale that divides a continuous data domain into several equal-width intervals and maps these intervals to discrete values in the range. It belongs to a type of segmented scale, primarily used for discretizing continuous data.
Similar to the threshold scale, quantize also maps continuous data to discrete values, but with the following differences:
The difference from the quantile scale is:
The quantize scale works as follows:
For example, with data domain [0, 100] and range ['Small', 'Medium', 'Large']:
The quantize scale is suitable for the following scenarios:
chart.options({type: 'cell',data: salaryData,encode: {color: 'salary',},scale: {color: {type: 'quantize',range: ['#eee', 'pink', 'red'], // Divide data into three groups, each corresponding to a color},},});
The quantize scale is primarily responsible for mapping continuous data domains to discrete ranges. Here are the configuration options for the quantize scale:
| Property | Description | Type | Default Value | Required |
|---|---|---|---|---|
| type | Scale type, must be 'quantize' | string | None | ✓ |
| domain | Set the domain range of the data | number[] | [0, 1] | |
| range | Set the range of data mapping values | any[] | [0.5] | |
| unknown | Return value for undefined, NaN, null empty values | any | undefined | |
| tickCount | Set the recommended number of ticks to generate, tickCount is only a suggestion value | number | 5 | |
| tickMethod | Set the method for generating ticks, commonly used for custom ticks | (min: number, max: number, count: number) => number[] | wilkinson-extended | |
| nice | Extend the domain range to make the output ticks display more friendly | boolean | false |
Below is an example of creating a heatmap using the quantize scale, dividing salary data into three equal-width intervals based on numerical values and mapping them to different colors:
import { Chart } from '@antv/g2';// Create a container elementconst container = document.createElement('div');const chart = new Chart({container: 'container',container,height: 340,});chart.options({type: 'cell',data: {type: 'fetch',value:'https://gw.alipayobjects.com/os/bmw-prod/89c20fe8-0c6f-46c8-b36b-4cb653dba8ed.json',transform: [{ type: 'map', callback: (d) => ({ salary: d }) }],},scale: {color: {type: 'quantize',range: ['#eee', 'pink', 'red'], // Divide data into three groups, corresponding to three colors},},legend: {color: {length: 400,labelFormatter: '.0s', // Format legend labels using abbreviations (e.g., 10K instead of 10000)},},encode: {y: (_, i) => (i % 5) + 1, // Set the row position of the cellx: (_, i) => ((i / 5) | 0) + 1, // Set the column position of the cellcolor: 'salary', // Map salary data to the color channel},style: {stroke: '#000', // Set cell border colorinset: 2, // Set cell padding},animate: {enter: { type: 'fadeIn' }, // Add fade-in animation effect},});chart.render();
In the above example:
.0s formatter to display large numbers in a more readable form (e.g., 10K)| Scale Type | Data Type | Segmentation Method | Use Case |
|---|---|---|---|
| quantize | Continuous | Equal-width | Uniform data distribution, need to group by range |
| quantile | Continuous | Equal-frequency | Uneven data distribution, need equal data per group |
| threshold | Continuous | Custom thresholds | Need to group by specific thresholds (e.g., pass/fail) |
The following example shows the difference between quantize and quantile scales when handling skewed data:
const { Chart } = G2;const chart = new Chart({container: 'container',});const container = chart.getContainer();// Create a skewed distribution dataset using integer valuesconst generateSkewedData = () => {const data = [];// Most data concentrated in low value areafor (let i = 0; i < 60; i++) {// Use integer values to avoid decimal overlapdata.push({value: Math.floor(5 + Math.random() * 25),type: 'Skewed Data',});}// Few data points distributed in high value area, more scatteredfor (let i = 0; i < 15; i++) {data.push({value: Math.floor(60 + Math.random() * 20),type: 'Skewed Data',});}// Add some middle values to make distribution more obviousfor (let i = 0; i < 10; i++) {data.push({value: Math.floor(40 + Math.random() * 15),type: 'Skewed Data',});}return data;};const data = generateSkewedData();// Create two charts for comparisoncontainer.style.display = 'flex';container.style.flexDirection = 'column';container.style.gap = '40px'; // Increase spacingcontainer.style.width = '100%';container.style.maxWidth = '800px';container.style.margin = '0 auto'; // Center display// Add titleconst title = document.createElement('h3');title.textContent = 'quantize vs quantile Scale Comparison';title.style.textAlign = 'center';title.style.marginBottom = '10px';container.appendChild(title);// quantize scale chartconst chart1Container = document.createElement('div');chart1Container.style.width = '100%';chart1Container.style.height = '220px'; // Increase heightcontainer.appendChild(chart1Container);const chart1 = new G2.Chart({container: chart1Container,height: 220,autoFit: true, // Auto-fit container sizepadding: [50, 100, 70, 100], // Increase padding, leave more space for labels});chart1.options({type: 'point',data,title: {text: 'quantize Scale (Equal-width Segmentation)',style: {fontSize: 14,fontWeight: 'bold',},},scale: {color: {type: 'quantize',range: ['#e8f4f8', '#a8d5e5', '#4ba3c3', '#0a6c93'], // 4 color segments},value: {nice: true,tickCount: 5, // Reduce tick countformatter: '.0f', // Use G2 built-in formatter to display integers},},encode: {x: 'value',y: 'type',color: 'value',shape: 'circle',size: 8,},style: {fillOpacity: 0.8,stroke: '#fff',lineWidth: 1,},legend: {color: {position: 'top',length: 200, // Set legend lengthlabelFormatter: '.0f', // Use G2 built-in formatter to display integers},},axis: {y: false,x: {labelSpacing: 10, // Increase label spacinglabelFormatter: '.0f', // Use G2 built-in formatter to display integerstickCount: 5, // Reduce tick count},},});chart1.render();// quantile scale chartconst chart2Container = document.createElement('div');chart2Container.style.width = '100%';chart2Container.style.height = '220px'; // Increase heightcontainer.appendChild(chart2Container);const chart2 = new G2.Chart({container: 'container',container: chart2Container,height: 220,autoFit: true, // Auto-fit container sizepadding: [50, 100, 70, 100], // Increase padding, leave more space for labels});chart2.options({type: 'point',data,title: {text: 'quantile Scale (Equal-frequency Segmentation)',style: {fontSize: 14,fontWeight: 'bold',},},scale: {color: {type: 'quantile',range: ['#e8f4f8', '#a8d5e5', '#4ba3c3', '#0a6c93'], // 4 color segments},value: {nice: true,tickCount: 5, // Reduce tick countformatter: '.0f', // Use G2 built-in formatter to display integers},},encode: {x: 'value',y: 'type',color: 'value',shape: 'circle',size: 8,},style: {fillOpacity: 0.8,stroke: '#fff',lineWidth: 1,},legend: {color: {position: 'top',length: 200, // Set legend lengthlabelFormatter: '.0f', // Use G2 built-in formatter to display integers},},axis: {y: false,x: {labelSpacing: 10, // Increase label spacinglabelFormatter: '.0f', // Use G2 built-in formatter to display integerstickCount: 5, // Reduce tick count},},});chart2.render();
In the above comparison example:
Below is a more complex example showing how to use the quantize scale to create multiple segments and customize the data domain:
import { Chart } from '@antv/g2';// Create a container elementconst container = document.createElement('div');const chart = new Chart({container: 'container',container,height: 300,});// Generate test dataconst data = Array.from({ length: 100 }, (_, i) => ({value: Math.random() * 100,id: i + 1,}));chart.options({type: 'point',data,scale: {color: {type: 'quantize',domain: [0, 100], // Custom data domainrange: ['#e8f4f8','#d1e6f0','#a8d5e5','#7ec2da','#4ba3c3','#2385ab','#0a6c93',], // 7 colors corresponding to 6 equal-width intervals},y: {nice: true,},},encode: {x: 'id',y: 'value',color: 'value', // Map values to color channelshape: 'circle',size: 10,},style: {fillOpacity: 0.8,stroke: '#fff',lineWidth: 1,},legend: {color: {length: 300,labelFormatter: '.0f', // Format legend labels as integers},},axis: {y: {title: 'Value',},x: {title: 'ID',},},});chart.render();
Here is a complete example using G2 declarative syntax (G2Spec) to configure the quantize scale:
const spec = {type: 'cell',width: 900,height: 300,data: {type: 'fetch',value:'https://gw.alipayobjects.com/os/bmw-prod/89c20fe8-0c6f-46c8-b36b-4cb653dba8ed.json',transform: [{ type: 'map', callback: (d) => ({ salary: d }) }],},scale: {color: {type: 'quantize',range: ['#eeeeee', '#ffc3ce', '#ff0d0d'], // Define three color intervals},},legend: {color: {labelFormatter: '.0s', // Format legend labels},},encode: {y: (_, i) => (i % 5) + 1,x: (_, i) => ((i / 5) | 0) + 1,color: 'salary', // Map salary data to color channel},style: {stroke: '#000',inset: 2,},};// Create a container elementconst container = document.createElement('div');// Render using Chartconst chart = new G2.Chart(container);chart.options(spec);chart.render();
This example demonstrates how to use G2 declarative syntax to create a heatmap using the quantize scale, including the following features:
When using the quantize scale, pay attention to the following points:
Segment Boundary Calculation: Segment boundaries are determined by the minimum and maximum values of the data domain and the length of the range array. For example, for data domain [0, 100] and range length of 3, the boundary points are 33.33 and 66.67.
Scale Selection: Choose quantize if you want to segment evenly by value range; choose quantile if you want each segment to contain the same number of data points.
Data Domain Setting: You can customize the data domain by setting the domain property, for example domain: [0, 100]. If not set, G2 will automatically calculate an appropriate data domain based on the data.
Data Distribution Consideration: The quantize scale is suitable for processing continuous numerical data with relatively uniform distribution. If the data distribution is very uneven (such as long-tail distribution), the quantile scale might be more appropriate.
Nice Ticks: When the nice parameter is set to true, it extends the range of the data domain to make boundary values more "friendly" (usually integers or easily understandable values), which helps generate more readable tick marks and legend labels.