UNHCR Logo
  • Guidance
  • Chart types
  • Resources
  • Tutorials
  • Product gallery
Tutorials
  • R
    • Change over time
    • Comparison
    • Correlation
    • Distribution
    • Geospatial
    • Part-to-a-whole
    • Ranking
  • Matplotlib
    • Change over time
    • Comparison
    • Correlation
    • Distribution
    • Part-to-a-whole
    • Ranking
  • Plotly Python
    • Comparison
  • D3
    • Change over time
    • Comparison
    • Correlation
    • Distribution
    • Geospatial
    • Part-to-a-whole
On this page
  • Histogram
  • Population Pyramid
  1. Home
  2. Tutorials
  3. D3
  4. Distribution

Histogram

A histogram displays the distribution of data over a continuous interval or specific time period. The height of each bar in a histogram indicates the frequency of data points within the interval/bin.

More about: Histogram - Other tutorials: R Matplotlib

            
              <!DOCTYPE html>
              <meta charset="utf-8">
              <!-- Include d3 library -->
              <script src="https://d3js.org/d3.v7.min.js"></script>
              <!-- Create a container to host the chart -->
              <div id="histogram_container"></div>
            
          
            
                             
            
          
            

              // set the dimensions and margins of the graph
              const margin = {top: 60, right: 20, bottom: 50, left: 40};
              const width = 450 - margin.left - margin.right;
              const height = 350 - margin.top - margin.bottom;

              // append the svg object to the body of the page
              const svg = d3.select("#histogram_container")
                .append("svg")
                  .attr("width", "100%")
                  .attr("height", "100%")
                  .attr("viewBox", "0 0 450 350")
                  .attr("preserveAspectRatio", "xMinYMin")
                .append("g")
                  .attr("transform", `translate(${margin.left}, ${margin.top})`);

              // parse the Data
              d3.csv("https://raw.githubusercontent.com/GDS-ODSSS/unhcr-dataviz-platform/master/data/distribution/histogram.csv")
              .then(function(data){

              // X scale and Axis
              const xScale = d3.scaleLinear()
                .domain([0,100]) 
                .range([0, width]);
              svg
                .append('g')
                .attr("transform", `translate(0, ${height})`)
                .call(d3.axisBottom(xScale).tickSize(0).tickPadding(8));
              
              // Y scale and Axis
              const yScale = d3.scaleLinear()
                  .range([height, 0]);

              const yAxis = svg.append('g')

              // set horizontal grid line
              const GridLine = () => d3.axisLeft().scale(yScale);
              svg
                .append("g")
                  .attr("class", "grid")
                .call(GridLine()
                  .tickSize(-width,0,0)
                  .tickFormat("")
                  .ticks(10)
              ); 

              // create a tooltip
              const tooltip = d3.select("body")
                .append("div")
                  .attr("class", "tooltip");

              // tooltip events
              const mouseover = function(d) {
                  tooltip
                    .style("opacity", 1)
                  d3.select(this)
                    .style("stroke", "#EF4A60")
                    .style("opacity", .5)
              };
              const mousemove = function(event,d) {
                  tooltip
                  .html(`<b>Number of people</b>: ${d.length}`)
                    .style("top", event.pageY - 10 + "px")
                    .style("left", event.pageX + 10 + "px")
              };
              const mouseleave = function(d) {
                  tooltip
                    .style("opacity", 0)
                  d3.select(this)
                    .style("stroke", "none")
                    .style("opacity", 1)
              };
              
              // set the parameters for the histogram
              const histogram = d3.bin()
                .value(d => d.poc_age)
                .domain(xScale.domain())
                .thresholds(xScale.ticks(50));

              // prepare data for bars
              const bins = histogram(data)

              // Scale the range of the data in the y domain
              yScale.domain([0, 20]);

              // add the y Axis
              yAxis
                .call(d3.axisLeft(yScale).tickSize(0).tickPadding(4))
                .call(d => d.select(".domain").remove());

              // append the bar rectangles to the svg element
              svg
                .selectAll("rect")
                  .data(bins)
                .join("rect")
                  .attr("class", "bar")
                  .attr("x", 1)
                  .attr("transform", d => `translate(${xScale(d.x0)}, ${yScale(d.length)})`)
                  .attr("width", d => xScale(d.x1) - xScale(d.x0) - 1)
                  .attr("height", d => height - yScale(d.length))
                  .style("fill", "#0072BC")
                .on("mouseover", mouseover)
                .on("mousemove", mousemove)
                .on("mouseleave", mouseleave);
       
              // set title
              svg
                .append("text")
                  .attr("class", "chart-title")
                  .attr("x", -(margin.left)*0.4)
                  .attr("y", -(margin.top)/1.5)
                  .attr("text-anchor", "start")
                .text("Age distribution | 2020")
              
              // set X axis label
              svg
                .append("text")
                  .attr("class", "chart-label")
                  .attr("x", width/2)
                  .attr("y", height+margin.bottom/1.7)
                  .attr("text-anchor", "middle")
                .text("Age");

              // set Y axis label
              svg
                .append("text")
                  .attr("class", "chart-label")
                  .attr("x", -(margin.left)*0.4)
                  .attr("y", -(margin.top/5))
                  .attr("text-anchor", "start")
                .text("Number of people")
              
              // set source
              svg
                .append("text")
                  .attr("class", "chart-source")
                  .attr("x", -(margin.left)*0.4)
                  .attr("y", height + margin.bottom*0.7)
                  .attr("text-anchor", "start")
                .text("Source: UNHCR")

              // set copyright
              svg
                .append("text")
                  .attr("class", "copyright")
                  .attr("x", -(margin.left)*0.4)
                  .attr("y", height + margin.bottom*0.9)
                  .attr("text-anchor", "start")
                .text("©UNHCR, The UN Refugee Agency")
              })

            
          

Population Pyramid

A population pyramid consists of two histograms, one for each gender (conventionally, males on the left and females on the right) where the population numbers are shown horizontally (X-axis) and the age vertically (Y-axis).

More about: Population pyramid - Other tutorials: R Matplotlib

            
              <!DOCTYPE html>
              <meta charset="utf-8">
              <!-- Include d3 library -->
              <script src="https://d3js.org/d3.v7.min.js"></script>
              <!-- Create a container to host the chart -->
              <div id="population_pyramid_container"></div>
            
          
            
                             
            
          
            

              // set the dimensions and margins of the graph
              const margin = {top: 60, right: 20, bottom: 50, left: 60};
              const width = 450 - margin.left - margin.right;
              const height = 350 - margin.top - margin.bottom;

              // append the svg object to the body of the page
              const svg = d3.select("#population_pyramid_container")
                .append("svg")
                  .attr("width", "100%")
                  .attr("height", "100%")
                  .attr("viewBox", "0 0 450 350")
                  .attr("preserveAspectRatio", "xMinYMin")
                .append("g")
                  .attr("transform", `translate(${margin.left}, ${margin.top})`);

              // parse the Data
              d3.csv("https://raw.githubusercontent.com/GDS-ODSSS/unhcr-dataviz-platform/master/data/distribution/population_pyramid.csv")
              .then(function(data){  

              // X scale and Axis
              const xScaleMale = d3.scaleLinear()
                .domain([0, d3.max(data, d => +d.male)]) 
                .range([width/2, 0]);
              svg
                .append("g")
                    .attr("transform", `translate(0, ${height})`)
                .call(d3.axisBottom(xScaleMale).tickSize(0).tickPadding(3).ticks(7, "%"))
                .call(function(d) { return d.select(".domain").remove()});

              const xScaleFemale = d3.scaleLinear()
                .domain([0, d3.max(data, d => +d.female)])
                .range([width/2, width]);
              svg
                .append("g")
                    .attr("transform", `translate(0, ${height})`)
                .call(d3.axisBottom(xScaleFemale).tickSize(0).tickPadding(3).ticks(7, "%"))
                .call(function(d) { return d.select(".domain").remove()});

              // set vertical grid line
              const GridLineF = function() { return d3.axisBottom().scale(xScaleFemale)};
              svg
                .append("g")
                  .attr("class", "grid")
                .call(GridLineF()
                  .tickSize(height,0,0)
                  .tickFormat("")
                  .ticks(7)
              );
              const GridLineM = function() { return d3.axisBottom().scale(xScaleMale)};
              svg
                .append("g")
                  .attr("class", "grid")
                .call(GridLineM()
                  .tickSize(height,0,0)
                  .tickFormat("")
                  .ticks(7)
              );
              
              // Y scale and Axis
              const yScale = d3.scaleBand()
                  .domain(data.map(d => d.ages))
                  .range([height, 0])
                  .padding(.25);
              svg
                  .append("g")
                  .call(d3.axisLeft(yScale).tickSize(0).tickPadding(15))
                  .call(d => d.select(".domain").remove());

              // create a tooltip
              const tooltip = d3.select("body")
                .append("div")
                  .attr("class", "tooltip");

              // tooltip events
              const mouseover = function(d) {
                  tooltip
                    .style("opacity", 1)
                  d3.select(this)
                    .style("stroke", "#EF4A60")
                    .style("opacity", .5)
              };
              const mousemove1 = function(event,d) {
                
                  tooltip
                  .html( `${d.male*100}%`)
                    .style("top", event.pageY - 10 + "px")
                    .style("left", event.pageX + 10 + "px");
              };
              const mousemove2 = function(event,d) {
                tooltip
                .html( `${d.female*100}%`)
                  .style("top", event.pageY - 10 + "px")
                  .style("left", event.pageX + 10 + "px")
            };
              const mouseleave = function(d) {
                  tooltip
                    .style("opacity", 0)
                  d3.select(this)
                    .style("stroke", "none")
                    .style("opacity", 1)
              };
              
              // create male bars
              svg
                .selectAll(".maleBar")
                  .data(data)
                .join("rect")
                  .attr("class", "barMale")
                  .attr("x", d => xScaleMale(d.male))
                  .attr("y", d => yScale(d.ages))
                  .attr("width", d => width/2 - xScaleMale(d.male))
                  .attr("height", yScale.bandwidth())
                  .style("fill", "#18375F")
                .on("mouseover", mouseover)
                .on("mousemove", mousemove1)
                .on("mouseleave", mouseleave)

              // create female bars
              svg
                  .selectAll(".femaleBar")
                    .data(data)
                  .join("rect")
                    .attr("class", "barFemale")
                    .attr("x", xScaleFemale(0))
                    .attr("y", d => yScale(d.ages))
                    .attr("width", d => xScaleFemale(d.female) - xScaleFemale(0))
                    .attr("height", yScale.bandwidth())
                    .style("fill", "#0072BC")
                  .on("mouseover", mouseover)
                  .on("mousemove", mousemove2)
                  .on("mouseleave", mouseleave)
       
              // set title
              svg
                .append("text")
                  .attr("class", "chart-title")
                  .attr("x", -(margin.left)*0.7)
                  .attr("y", -(margin.top)/1.5)
                  .attr("text-anchor", "start")
                .text("Demographics of forcibly displaced people | 2020")

              // set source
              svg
                .append("text")
                  .attr("class", "chart-source")
                  .attr("x", -(margin.left)*0.7)
                  .attr("y", height + margin.bottom*0.7)
                  .attr("text-anchor", "start")
                .text("Source: UNHCR")

              // set copyright
              svg
                .append("text")
                  .attr("class", "copyright")
                  .attr("x", -(margin.left)*0.7)
                  .attr("y", height + margin.bottom*0.9)
                  .attr("text-anchor", "start")
                .text("©UNHCR, The UN Refugee Agency")

              //set legend
              svg
                  .append("rect")
                      .attr("x", -(margin.left)*0.7)
                      .attr("y", -(margin.top/3))
                      .attr("width", 13)
                      .attr("height", 13)
                      .style("fill", "#18375F")
              svg
                  .append("text")
                      .attr("class", "legend")
                      .attr("x", -(margin.left)*0.6+15)
                      .attr("y", -(margin.top/5.5))
                  .text("Male")
              svg
                  .append("rect")
                      .attr("x", 40)
                      .attr("y", -(margin.top/3))
                      .attr("width", 13)
                      .attr("height", 13)
                      .style("fill", "#0072BC")
              svg
                  .append("text")
                      .attr("class", "legend")
                      .attr("x", 60)
                      .attr("y", -(margin.top/5.5))
                  .text("Female")

              })

            
          
Contact us
  • Guidance
  • Chart types
  • Resources
  • Tutorials
  • Product gallery

© UNHCR