Skip to content

Column Chart (Vertical Bar)

Overview

Displays data as vertical columns, perfect for comparing categorical data over time or across different categories. The standard choice for most comparison visualizations.

Sample Preview

Column Chart Sample

Best Use Cases

  • Monthly Survey Responses - Track response volumes over time
  • Satisfaction by Business Unit - Compare scores across departments
  • Performance Metrics - Show KPI values across categories

Sample Data Structure

AskRITA UniversalChartData

from askrita.sqlagent.formatters.DataFormatter import UniversalChartData, ChartDataset, DataPoint

column_data = UniversalChartData(
    type="bar",  # Note: "bar" type creates vertical columns in AskRITA
    title="Monthly Survey Response Volume",
    labels=["Jan", "Feb", "Mar", "Apr", "May", "Jun"],
    datasets=[
        ChartDataset(
            label="Response Count",
            data=[
                DataPoint(y=2450, category="Jan"),
                DataPoint(y=2890, category="Feb"),
                DataPoint(y=3120, category="Mar"),
                DataPoint(y=2780, category="Apr"),
                DataPoint(y=3450, category="May"),
                DataPoint(y=3890, category="Jun")
            ]
        )
    ],
    xAxisLabel="Month",
    yAxisLabel="Response Count"
)

Google Charts Implementation

HTML Structure

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
</head>
<body>
    <div id="column_chart" style="width: 900px; height: 500px;"></div>
</body>
</html>

JavaScript Code

google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawColumnChart);

function drawColumnChart() {
    var data = google.visualization.arrayToDataTable([
        ['Month', 'Response Count'],
        ['Jan', 2450],
        ['Feb', 2890],
        ['Mar', 3120],
        ['Apr', 2780],
        ['May', 3450],
        ['Jun', 3890]
    ]);

    var options = {
        title: 'Monthly Survey Response Volume',
        titleTextStyle: {
            fontSize: 18,
            bold: true
        },
        width: 900,
        height: 500,
        hAxis: {
            title: 'Month'
        },
        vAxis: {
            title: 'Response Count',
            format: '#,###',
            minValue: 0
        },
        colors: ['#4285f4'],
        backgroundColor: 'white',
        chartArea: {
            left: 80,
            top: 80,
            width: '80%',
            height: '70%'
        },
        bar: {
            groupWidth: '75%'
        }
    };

    var chart = new google.visualization.ColumnChart(document.getElementById('column_chart'));
    chart.draw(data, options);
}

Multi-Series Column Chart

function drawMultiSeriesColumnChart() {
    var data = google.visualization.arrayToDataTable([
        ['Business Unit', 'Q1 Satisfaction', 'Q2 Satisfaction', 'Q3 Satisfaction'],
        ['Retail Store', 8.2, 8.4, 8.6],
        ['Walk-in Clinic', 8.5, 8.7, 8.8],
        ['Wellness Center', 7.9, 8.1, 8.3],
        ['Digital Services', 6.8, 7.2, 7.5]
    ]);

    var options = {
        title: 'Quarterly Satisfaction Scores by Business Unit',
        width: 900,
        height: 500,
        hAxis: {
            title: 'Business Unit'
        },
        vAxis: {
            title: 'Satisfaction Score (1-10)',
            minValue: 0,
            maxValue: 10
        },
        colors: ['#4285f4', '#34a853', '#fbbc04'],
        legend: {
            position: 'top',
            alignment: 'center'
        }
    };

    var chart = new google.visualization.ColumnChart(document.getElementById('column_chart'));
    chart.draw(data, options);
}

React Implementation

import React, { useEffect, useRef } from 'react';

interface ColumnChartProps {
    data: Array<{
        category: string;
        value: number;
        series?: string;
    }>;
    title?: string;
    width?: number;
    height?: number;
    xAxisLabel?: string;
    yAxisLabel?: string;
    multiSeries?: boolean;
}

const ColumnChart: React.FC<ColumnChartProps> = ({
    data,
    title = "Column Chart",
    width = 900,
    height = 500,
    xAxisLabel = "Category",
    yAxisLabel = "Value",
    multiSeries = false
}) => {
    const chartRef = useRef<HTMLDivElement>(null);

    useEffect(() => {
        if (!window.google || !chartRef.current) return;

        let chartData;

        if (multiSeries) {
            // Group data by category and series
            const grouped = data.reduce((acc, item) => {
                if (!acc[item.category]) acc[item.category] = {};
                acc[item.category][item.series || 'Value'] = item.value;
                return acc;
            }, {} as Record<string, Record<string, number>>);

            const categories = Object.keys(grouped);
            const series = [...new Set(data.map(item => item.series || 'Value'))];

            chartData = new google.visualization.DataTable();
            chartData.addColumn('string', 'Category');
            series.forEach(s => chartData.addColumn('number', s));

            const rows = categories.map(cat => [
                cat,
                ...series.map(s => grouped[cat][s] || 0)
            ]);
            chartData.addRows(rows);
        } else {
            chartData = new google.visualization.DataTable();
            chartData.addColumn('string', 'Category');
            chartData.addColumn('number', 'Value');

            const rows = data.map(item => [item.category, item.value]);
            chartData.addRows(rows);
        }

        const options = {
            title: title,
            width: width,
            height: height,
            hAxis: {
                title: xAxisLabel
            },
            vAxis: {
                title: yAxisLabel,
                minValue: 0
            },
            colors: ['#4285f4', '#34a853', '#fbbc04', '#ea4335'],
            chartArea: {
                left: 80,
                top: 80,
                width: '80%',
                height: '70%'
            }
        };

        const chart = new google.visualization.ColumnChart(chartRef.current);
        chart.draw(chartData, options);
    }, [data, title, width, height, xAxisLabel, yAxisLabel, multiSeries]);

    return <div ref={chartRef} style={{ width: `${width}px`, height: `${height}px` }} />;
};

export default ColumnChart;

Survey Data Examples

// Monthly satisfaction scores
var data = google.visualization.arrayToDataTable([
    ['Month', 'NPS Score', 'CSAT Score'],
    ['Jan 2024', 68, 8.2],
    ['Feb 2024', 71, 8.4],
    ['Mar 2024', 74, 8.6],
    ['Apr 2024', 72, 8.3],
    ['May 2024', 76, 8.7],
    ['Jun 2024', 78, 8.9]
]);

var options = {
    title: 'Customer Satisfaction Trends',
    hAxis: { title: 'Month' },
    vAxes: {
        0: { title: 'NPS Score', minValue: 0, maxValue: 100 },
        1: { title: 'CSAT Score', minValue: 0, maxValue: 10 }
    },
    series: {
        0: { targetAxisIndex: 0, color: '#4285f4' },
        1: { targetAxisIndex: 1, color: '#34a853' }
    }
};

Response Volume by Channel

// Survey responses by different channels
var data = google.visualization.arrayToDataTable([
    ['Channel', 'Responses'],
    ['Email Survey', 15420],
    ['SMS Survey', 8932],
    ['Phone Survey', 5621],
    ['In-Store Kiosk', 3210],
    ['Mobile App', 2890],
    ['Website Pop-up', 1456]
]);

var options = {
    title: 'Survey Response Volume by Channel',
    hAxis: { title: 'Survey Channel' },
    vAxis: { 
        title: 'Number of Responses',
        format: '#,###'
    },
    colors: ['#ff7f0e'],
    bar: { groupWidth: '70%' }
};

Departmental Performance Comparison

// Satisfaction scores across departments
var data = google.visualization.arrayToDataTable([
    ['Department', 'Current Quarter', 'Previous Quarter', 'Target'],
    ['Pharmacy', 8.4, 8.2, 8.5],
    ['Walk-in Clinic', 8.7, 8.5, 8.5],
    ['Wellness Center', 8.1, 7.9, 8.5],
    ['Customer Service', 7.8, 7.6, 8.5],
    ['Digital Experience', 7.2, 6.9, 8.5]
]);

var options = {
    title: 'Department Satisfaction Scores vs Target',
    hAxis: { title: 'Department' },
    vAxis: { 
        title: 'Satisfaction Score (1-10)',
        minValue: 6,
        maxValue: 9
    },
    colors: ['#4285f4', '#9aa0a6', '#ea4335'],
    legend: { position: 'top' }
};

Advanced Features

Stacked Column Chart

function drawStackedColumnChart() {
    var data = google.visualization.arrayToDataTable([
        ['Service Area', 'Promoters', 'Passives', 'Detractors'],
        ['Retail Store', 65, 25, 10],
        ['Walk-in Clinic', 70, 22, 8],
        ['Wellness Center', 58, 30, 12],
        ['Digital Services', 45, 35, 20]
    ]);

    var options = {
        title: 'NPS Distribution by Service Area',
        isStacked: true,
        hAxis: { title: 'Service Area' },
        vAxis: { title: 'Percentage of Customers' },
        colors: ['#28a745', '#ffc107', '#dc3545']
    };

    var chart = new google.visualization.ColumnChart(document.getElementById('column_chart'));
    chart.draw(data, options);
}

100% Stacked Column Chart

function draw100PercentStackedChart() {
    var data = google.visualization.arrayToDataTable([
        ['Service Area', 'Promoters', 'Passives', 'Detractors'],
        ['Retail Store', 65, 25, 10],
        ['Walk-in Clinic', 70, 22, 8],
        ['Wellness Center', 58, 30, 12],
        ['Digital Services', 45, 35, 20]
    ]);

    var options = {
        title: 'NPS Distribution by Service Area (Percentage)',
        isStacked: 'percent',
        hAxis: { title: 'Service Area' },
        vAxis: { 
            title: 'Percentage',
            format: '#\'%\''
        },
        colors: ['#28a745', '#ffc107', '#dc3545']
    };

    var chart = new google.visualization.ColumnChart(document.getElementById('column_chart'));
    chart.draw(data, options);
}

Interactive Column Chart with Drill-Down

function drawInteractiveColumnChart() {
    var chart = new google.visualization.ColumnChart(document.getElementById('column_chart'));

    google.visualization.events.addListener(chart, 'select', function() {
        var selection = chart.getSelection();
        if (selection.length > 0) {
            var row = selection[0].row;
            var col = selection[0].column;

            if (col > 0) { // Not the category column
                var category = data.getValue(row, 0);
                var series = data.getColumnLabel(col);
                var value = data.getValue(row, col);

                showDrillDownData(category, series, value);
            }
        }
    });

    chart.draw(data, options);
}

function showDrillDownData(category, series, value) {
    // Load detailed breakdown for selected category/series
    const detailModal = document.getElementById('detail-modal');
    detailModal.innerHTML = `
        <h3>${category} - ${series}</h3>
        <p>Value: ${value}</p>
        <div id="detail-chart"></div>
    `;
    detailModal.style.display = 'block';

    // Load and display detailed data
    loadDetailedData(category, series);
}

Key Features

  • Clear Comparison - Easy to compare values across categories
  • Multiple Series - Support for grouped and stacked columns
  • Time Series - Perfect for showing trends over time
  • Interactive - Selection and drill-down capabilities
  • Flexible Styling - Colors, spacing, and formatting options

When to Use

Perfect for: - Categorical data comparison - Time series with discrete periods - Multiple data series comparison - Part-to-whole analysis (stacked) - Performance dashboards

Avoid when: - Continuous time series (use line chart) - Too many categories (>12) - Precise value reading needed - Proportional relationships (use pie chart)

Performance Tips

// For large datasets, consider data aggregation
function aggregateData(data, maxCategories = 10) {
    if (data.length <= maxCategories) return data;

    const sorted = data.sort((a, b) => b.value - a.value);
    const top = sorted.slice(0, maxCategories - 1);
    const others = sorted.slice(maxCategories - 1);

    const othersSum = others.reduce((sum, item) => sum + item.value, 0);

    return [...top, { category: 'Others', value: othersSum }];
}

Documentation