Loading...
In G2, Data is primarily used to specify the data to be visualized and data transformation (pre-processing).
There are three main ways to configure data.
type: inline
, which defines an inline connector that directly passes in specific data. This is the default data source type in G2.({data: {type: 'inline', // Specify inline typevalue: [{ genre: 'Sports', sold: 275 },{ genre: 'Strategy', sold: 115 },{ genre: 'Action', sold: 120 },{ genre: 'Shooter', sold: 350 },{ genre: 'Other', sold: 150 },],},});
type: fetch
, which defines a remote connector that obtains data from remote interfaces, making data sources dynamic. It supports parsing JSON, CSV and other formats, adapts to multi-scenario data integration, and improves development efficiency and interactive experience for applications like dashboards and monitoring systems.({data: {type: 'fetch', // Specify fetch typevalue: 'https://gw.alipayobjects.com/os/antvdemo/assets/data/scatter.json', // Remote address},});
({data: [{ genre: 'Sports', sold: 275 },{ genre: 'Strategy', sold: 115 },{ genre: 'Action', sold: 120 },{ genre: 'Shooter', sold: 350 },{ genre: 'Other', sold: 150 },],});
Data can be specified at the View level:
({type: 'view',data: [{ genre: 'Sports', sold: 275 },{ genre: 'Strategy', sold: 115 },{ genre: 'Action', sold: 120 },{ genre: 'Shooter', sold: 350 },{ genre: 'Other', sold: 150 },],});
Data bound to a view is transitive: it will be passed to marks in view.children
. If the mark does not have data, its data will be set; otherwise, there is no effect. This means that for marks that share data, you can bind the data to the view.
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',});chart.options({type: 'view',autoFit: true,data: [{ year: '1991', value: 3 },{ year: '1992', value: 4 },{ year: '1993', value: 3.5 },{ year: '1994', value: 5 },{ year: '1995', value: 4.9 },{ year: '1996', value: 6 },{ year: '1997', value: 7 },{ year: '1998', value: 9 },{ year: '1999', value: 13 },],children: [{ type: 'line', encode: { x: 'year', y: 'value' } },{ type: 'point', encode: { x: 'year', y: 'value' } },],});chart.render();
Data can also be specified at the Mark level:
({type: 'interval',data: [{ genre: 'Sports', sold: 275 },{ genre: 'Strategy', sold: 115 },{ genre: 'Action', sold: 120 },{ genre: 'Shooter', sold: 350 },{ genre: 'Other', sold: 150 },],});
Each mark has its own data, which means we can visualize multiple datasets in one view, such as the following interval annotation chart:
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',});chart.options({type: 'view',autoFit: true,children: [{type: 'rangeX',data: [{ year: [new Date('1933'), new Date('1945')], event: 'Nazi Rule' },{year: [new Date('1948'), new Date('1989')],event: 'GDR (East Germany)',},],encode: { x: 'year', color: 'event' },scale: { color: { independent: true, range: ['#FAAD14', '#30BF78'] } },style: { fillOpacity: 0.75 },tooltip: false,},{type: 'line',data: {type: 'fetch',value: 'https://assets.antv.antgroup.com/g2/year-population.json',},encode: { x: (d) => new Date(d.year), y: 'population', color: '#333' },},],});chart.render();
A complete data declaration consists of two parts: Connector and DataTransform. Connector is the way to get data, specified by data.type
, and data transform is the pre-processing function, specified by data.transform
.
({data: {type: 'fetch', // Specify connector type// Specify connector valuevalue:'https://gw.alipayobjects.com/os/basement_prod/6b4aa721-b039-49b9-99d8-540b3f87d339.json',transform: [// Specify transforms, multiple can be specified{ type: 'filter', callback: (d) => d.sex === 'gender' },{type: 'sort',callback: (a, b) => b.a - a.a,},],},});
Currently, G2 has the following built-in data transforms:
type | Description | Properties |
---|---|---|
custom | Custom data processing logic that allows users to define their own operation methods | custom |
ema | Calculate exponential moving average for data smoothing | ema |
filter | Filter data based on specified conditions | filter |
fold | Unfold multiple fields into specified key-value organization format for easier processing and analysis | fold |
join | Merge two data tables based on certain conditions to associate corresponding data rows | join |
kde | Estimate data distribution density, commonly used for probability density analysis | kde |
log | Print current data in the data transform flow to console for developers to debug data processing | log |
map | Perform mapping operations on data, converting one type of value to another | map |
pick | Select specified fields from data for extracting specific information | pick |
rename | Rename data fields for easier subsequent processing and reading | rename |
slice | Extract a subset of data, equivalent to data pagination or cropping | slice |
sort | Sort data with support for custom sorting rules | sort |
sortBy | Sort data by a specified field | sortBy |
Since data is bound to marks, data updating can be a bit complex. Using the following example:
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',});const interval = chart.interval().data([{ genre: 'Sports', sold: 275 },{ genre: 'Strategy', sold: 115 },{ genre: 'Action', sold: 120 },{ genre: 'Shooter', sold: 350 },{ genre: 'Other', sold: 150 },]).encode('x', 'genre').encode('y', 'sold');chart.render();
There are several ways to update the interval data in the above example:
// Update the data bound to intervalinterval.data(newData);// Update chart rendering through chartchart.render();
// Update interval data and render the chartinterval.changeData(newData);
chart.getNodesByType('rect')[0].changeData(data);
Here's an example of a line chart that updates data in real-time:
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',});// Format function: Convert timestamp to hh:mm:ss formatfunction formatTime(timestamp) {const date = new Date(timestamp);const hours = String(date.getHours()).padStart(2, '0'); // Pad to two digitsconst minutes = String(date.getMinutes()).padStart(2, '0');const seconds = String(date.getSeconds()).padStart(2, '0');return `${hours}:${minutes}:${seconds}`;}const data = [];chart.options({type: 'line',data: [],encode: {x: (d) => formatTime(d.time),y: 'temperature',color: 'type',shape: 'smooth',size: 2,},scale: {x: {nice: true,},},});chart.render();setInterval(function () {const now = new Date();const time = now.getTime();const temperature1 = ~~(Math.random() * 5) + 22;const temperature2 = ~~(Math.random() * 7) + 17;if (data.length >= 200) {data.shift();data.shift();}data.push({time, // Use formatted timetemperature: temperature1,type: 'Record 1',});data.push({time, // Use formatted timetemperature: temperature2,type: 'Record 2',});chart.changeData(data);}, 1000);
With the custom data transform capability, we can configure:
({data: {transform: [{type: 'custom',callback: customFn(), // Custom data processing function},],},});
The customFn
here can use external data processing libraries, greatly expanding G2's data processing capabilities. In the following example, we use the third-party library d3-regression to generate linear statistical regression lines:
import { regressionLinear } from 'd3-regression';node.data({// Use D3's regressionLinear to perform linear regression on datatransform: [{type: 'custom',callback: regressionLinear(),},],});
For more statistical regression line examples, see Data Analysis - Regression Lines.