Loading...
A typical bar chart, also known as a column chart, uses vertical or horizontal bars to display comparisons between different categories. One axis represents the categories being compared, while the other axis denotes the corresponding values.
Unlike histograms, bar charts cannot show changes in data across a continuous range. Instead, they represent categorical data and answer the question: "How many are there in each category?"
It’s important to note that bar charts can become cluttered when displaying too many categories, leading to overlapping labels and legibility issues. We'll demonstrate this below.
English Names: Column Chart, Bar Chart
Chart Type | Vertical Bar Chart |
---|---|
Suitable Data | A dataset containing one categorical field and one numerical field |
Functionality | Compares the size of numerical values across categories |
Data Mapping | Categorical data maps to the horizontal axis position Numerical data maps to bar height Categorical data can also map to color for better category distinction |
Data Size Limit | Recommended for no more than 12 data points |
Chart Type | Horizontal Bar Chart |
---|---|
Suitable Data | A dataset containing one categorical field and one numerical field |
Functionality | Compares the size of numerical values across categories |
Data Mapping | Categorical data maps to the vertical axis Numerical data maps to bar width |
Data Size Limit | Recommended for no more than 30 data points |
Example 1: Comparing Categorical Data
The chart below compares the sales of different game genres.
Genre | Sales |
---|---|
Sports | 27,500 |
Strategy | 11,500 |
Action | 6,000 |
Shooter | 3,500 |
Other | 1,500 |
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',theme: 'classic',});chart.options({type: 'interval',autoFit: true,data: [{ genre: 'Sports', sold: 275 },{ genre: 'Strategy', sold: 115 },{ genre: 'Action', sold: 120 },{ genre: 'Shooter', sold: 350 },{ genre: 'Other', sold: 150 },],encode: { x: 'genre', y: 'sold', color: 'genre' },interaction: [{type: 'elementHighlight',background: true,region: true,},],});chart.render();
Explanation:
genre
field maps to both position and color, differentiating game categories.sold
field maps to the bar length to represent sales volume.Example 1: Too Many Categories for a Vertical Bar Chart
When comparing population sizes across provinces, too many categories can cause text overlap issues, making labels harder to read. In such cases, horizontal bar charts are more effective.
Province | Population |
---|---|
Beijing | 19,612,368 |
Tianjin | 12,938,693 |
Hebei | 71,854,210 |
... | ... |
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',theme: 'classic',});chart.options({type: 'interval',autoFit: true,data: [{ province: 'Beijing', population: 19612368 },{ province: 'Tianjin', population: 12938693 },{ province: 'Hebei', population: 71854210 },{ province: 'Shanxi', population: 27500000 },{ province: 'Inner Mongolia', population: 24706291 },{ province: 'Liaoning', population: 43746323 },{ province: 'Jilin', population: 27452815 },{ province: 'Heilongjiang', population: 38313991 },{ province: 'Shanghai', population: 23019196 },{ province: 'Jiangsu', population: 78660941 },{ province: 'Zhejiang', population: 54426891 },{ province: 'Anhui', population: 59500468 },{ province: 'Fujian', population: 36894217 },{ province: 'Jiangxi', population: 44567797 },{ province: 'Shandong', population: 95792719 },{ province: 'Henan', population: 94029939 },{ province: 'Hubei', population: 57237727 },{ province: 'Hunan', population: 65700762 },{ province: 'Guangdong', population: 104320459 },{ province: 'Guangxi', population: 46023761 },{ province: 'Hainan', population: 8671485 },{ province: 'Chongqing', population: 28846170 },{ province: 'Sichuan', population: 80417528 },{ province: 'Guizhou', population: 34748556 },{ province: 'Yunnan', population: 45966766 },{ province: 'Tibet', population: 3002165 },{ province: 'Shaanxi', population: 37327379 },{ province: 'Gansu', population: 25575263 },{ province: 'Qinghai', population: 5626723 },],encode: { x: 'province', y: 'population' },axis: {y: {title: null,},x: {title: null,labelFontSize: 12,size: 100, // Size must be setlabelAutoEllipsis: {suffix: '..',minLength: 8,maxLength: 12,},labelAutoWrap: {wordWrapWidth: 80,maxLines: 2,recoverWhenFailed: true,},labelAutoRotate: {optionalAngles: [0, 45, 90], // Attempt to rotate by 0 degrees, 45 degrees, or 90 degreesrecoverWhenFailed: true, // If rotation fails, revert to the default angle},labelAutoHide: {keepHeader: true, // Retain the first tick labelkeepTail: true, // Retain the last tick label},},},interaction: [{type: 'elementHighlight',background: true,region: true,},],});chart.render();
Switching to a horizontal bar chart makes labels easier to read, as shown below:
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',theme: 'classic',});chart.options({type: 'interval',autoFit: true,data: [{ province: 'Beijing', population: 19612368 },{ province: 'Tianjin', population: 12938693 },{ province: 'Hebei', population: 71854210 },{ province: 'Shanxi', population: 27500000 },{ province: 'Inner Mongolia', population: 24706291 },{ province: 'Liaoning', population: 43746323 },{ province: 'Jilin', population: 27452815 },{ province: 'Heilongjiang', population: 38313991 },{ province: 'Shanghai', population: 23019196 },{ province: 'Jiangsu', population: 78660941 },{ province: 'Zhejiang', population: 54426891 },{ province: 'Anhui', population: 59500468 },{ province: 'Fujian', population: 36894217 },{ province: 'Jiangxi', population: 44567797 },{ province: 'Shandong', population: 95792719 },{ province: 'Henan', population: 94029939 },{ province: 'Hubei', population: 57237727 },{ province: 'Hunan', population: 65700762 },{ province: 'Guangdong', population: 104320459 },{ province: 'Guangxi', population: 46023761 },{ province: 'Hainan', population: 8671485 },{ province: 'Chongqing', population: 28846170 },{ province: 'Sichuan', population: 80417528 },{ province: 'Guizhou', population: 34748556 },{ province: 'Yunnan', population: 45966766 },{ province: 'Tibet', population: 3002165 },{ province: 'Shaanxi', population: 37327379 },{ province: 'Gansu', population: 25575263 },{ province: 'Qinghai', population: 5626723 },],encode: { x: 'province', y: 'population' },coordinate: { transform: [{ type: 'transpose' }] },axis: {y: {title: null,},x: {title: null,},},interaction: [{type: 'elementHighlight',background: true,region: true,},],});chart.render();
Example 2: Not Suitable for Trends
Bar charts use bar length to compare categorical data but are not effective for showing continuous trends.
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',theme: 'classic',});chart.options({type: 'interval',autoFit: true,data: [{ day: '2015/9/1', share: 10 },{ day: '2015/9/2', share: 12 },{ day: '2015/9/3', share: 11 },{ day: '2015/9/4', share: 15 },{ day: '2015/9/5', share: 20 },{ day: '2015/9/6', share: 22 },{ day: '2015/9/7', share: 21 },{ day: '2015/9/8', share: 25 },{ day: '2015/9/9', share: 31 },{ day: '2015/9/10', share: 32 },{ day: '2015/9/11', share: 28 },{ day: '2015/9/12', share: 29 },{ day: '2015/9/13', share: 40 },{ day: '2015/9/14', share: 41 },{ day: '2015/9/15', share: 45 },{ day: '2015/9/16', share: 50 },{ day: '2015/9/17', share: 65 },{ day: '2015/9/18', share: 45 },{ day: '2015/9/19', share: 50 },{ day: '2015/9/20', share: 51 },{ day: '2015/9/21', share: 65 },{ day: '2015/9/22', share: 60 },{ day: '2015/9/23', share: 62 },{ day: '2015/9/24', share: 65 },{ day: '2015/9/25', share: 45 },{ day: '2015/9/26', share: 55 },{ day: '2015/9/27', share: 59 },{ day: '2015/9/28', share: 52 },{ day: '2015/9/29', share: 53 },{ day: '2015/9/30', share: 40 },],encode: { x: 'day', y: 'share' },axis: {y: {title: null,},x: {title: null,},},interaction: [{type: 'elementHighlight',background: true,region: true,},],});chart.render();
For instance, a bar chart is less ideal for showing daily stock prices for September 2015 compared to a line chart or area chart.
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',theme: 'classic',});chart.options({type: 'view',autoFit: true,data: [{ day: '2015/9/1', share: 10 },{ day: '2015/9/2', share: 12 },{ day: '2015/9/3', share: 11 },{ day: '2015/9/4', share: 15 },{ day: '2015/9/5', share: 20 },{ day: '2015/9/6', share: 22 },{ day: '2015/9/7', share: 21 },{ day: '2015/9/8', share: 25 },{ day: '2015/9/9', share: 31 },{ day: '2015/9/10', share: 32 },{ day: '2015/9/11', share: 28 },{ day: '2015/9/12', share: 29 },{ day: '2015/9/13', share: 40 },{ day: '2015/9/14', share: 41 },{ day: '2015/9/15', share: 45 },{ day: '2015/9/16', share: 50 },{ day: '2015/9/17', share: 65 },{ day: '2015/9/18', share: 45 },{ day: '2015/9/19', share: 50 },{ day: '2015/9/20', share: 51 },{ day: '2015/9/21', share: 65 },{ day: '2015/9/22', share: 60 },{ day: '2015/9/23', share: 62 },{ day: '2015/9/24', share: 65 },{ day: '2015/9/25', share: 45 },{ day: '2015/9/26', share: 55 },{ day: '2015/9/27', share: 59 },{ day: '2015/9/28', share: 52 },{ day: '2015/9/29', share: 53 },{ day: '2015/9/30', share: 40 },],encode: { x: 'day', y: 'share' },axis: {y: {title: null,},x: {title: null,tickFilter: (_, i) => i % 2 !== 0, // Filter the tick marks on the x-axis to display only every other tick.},},children: [{type: 'area',style: {opacity: 0.6,},},{type: 'line',style: {lineWidth: 3,},},],});chart.render();