Data Visualization Projects - Visualize Data with a Heat Map

I’m still failing these test:

8. The “data-month”, “data-year” of each cell should be within the range of the data.

9. My heat map should have cells that align with the corresponding month on the y-axis.

I really cannot understand why…
Everything seems to line up.

import * as d3 from "https://cdn.skypack.dev/d3@7.8.2";

function calculateHex(v) {
  if (v >= 2.8 && v <= 5.0) {
    return "#008080";
  } else if (v > 5.0 && v <= 7.2) {
    return "#FFFF00";
  } else if (v > 7.2 && v <= 9.5) {
    return "#FFA500";
  } else if (v > 9.5 && v <= 12.8) {
    return "#FF0000";
  } else {
    return "lightblue";
  }
}

const w = 1603;
const h = 540;
const padding = 150;

const title = d3
  .select("main")
  .append("h1")
  .attr("id", "title")
  .text("Monthly Global Land-Surface Temperature");

const subtitle = d3
  .select("main")
  .append("h4")
  .attr("id", "description")
  .text("1753 - 2015: base temperature 8.66℃");

const svg = d3.select("main").append("svg").attr("width", w).attr("height", h);

const url =
  "https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/global-temperature.json";

document.addEventListener("DOMContentLoaded", function () {
  fetch(url)
    .then((response) => response.json())
    .then((data) => {
      const dataset = data.monthlyVariance.map(function (item) {
        return {
          year: item.year,
          month: item.month,
          variance: item.variance,
          actualTemp: 8.66 + item.variance,
          colorHex: calculateHex(8.66 + item.variance)
        };
      });

      console.log(dataset);

      const minYears = d3.min(dataset, (d) => d.year);

      const maxYears = d3.max(dataset, (d) => d.year);

      const minMonth = d3.min(dataset, (d) => d.month);

      const maxMonth = d3.max(dataset, (d) => d.month);

      console.log(minYears, maxYears, minMonth, maxMonth);

      const yScale = d3
        .scaleBand()
        .domain([12,11,10,9,8,7,6,5,4,3,2,1])
        .range([h - padding, padding]);

      const xScale = d3
        .scaleLinear()
        .domain([1752, maxYears])
        .range([padding, w - padding]);

      const yAxis = d3.axisLeft(yScale);

      const xAxis = d3.axisBottom(xScale);

      svg
        .append("g")
        .attr("id", "x-axis")
        .attr("transform", `translate(0,${h - padding})`)
        .call(xAxis);

      svg
        .append("g")
        .attr("id", "y-axis")
        .attr("transform", `translate(${padding},0)`)
        .call(yAxis);

      svg
        .selectAll("rect")
        .data(dataset)
        .enter()
        .append("rect")
        .attr("x", (d, i) => xScale(d.year))
        .attr("y", (d, i) => yScale(d.month))
        .attr("width", 5)
        .attr("height",20)
        .attr("data-month", (d) => d.month)
        .attr("data-year", (d) => d.year)
        .attr("data-temp", (d) => d.actualTemp)
        .attr("class", "cell")
        .style("fill", (d) => d.colorHex);
    });
});

Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36

Challenge: Data Visualization Projects - Visualize Data with a Heat Map

Link to the challenge:

Link to the codepen

Hola

@ emibonezzi

8. The “data-month”, “data-year” of each cell should be within the range of the data.

Par este restale uno al valor del attr data-month

.attr("data-month", (d) => d.month - 1)

9. My heat map should have cells that align with the corresponding month on the y-axis.

En este caso necesitas que los meses del año se representen en el formato:

January, February, March… actualmente tienes 1, 2, 3…

1 Like

Hi there, i think you need to use xScale methods on d.year and yScale on d.months-1 in your attribute definitions. I hope that helps

The alignment tests implicitly check the labels and values of the objects that are being checked for alignment so that the test fails if they are mislabeled or out of alignment. As others have pointed out, you need the JavaScript conventional month numbers for the month attributes (0-11) and the actual month names for labels on the axis. D3’s time parsing functions are useful in these cases.

You may also encounter trouble with the x-axis using a linear scale instead of a time scale.

If you have trouble with other attributes or properties, simply log from the callback setting the value like

         .attr("data-month", (d) => {
           console.log(d.month);
           return d.month;
         })

instead of

         .attr("data-month", (d) => d.month)

Additionally, there is no need to import D3 like you did on codepen. Simply search for it and add it via the JS configuration tab as you did the fCC testing bundle.

Thanks for the help.
I have implemented your suggestions in my code:

import * as d3 from "https://cdn.skypack.dev/d3@7.8.2";

function calculateHex(v) {
  if (v >= 2.8 && v <= 5.0) {
    return "#008080";
  } else if (v > 5.0 && v <= 7.2) {
    return "#FFFF00";
  } else if (v > 7.2 && v <= 9.5) {
    return "#FFA500";
  } else if (v > 9.5 && v <= 12.8) {
    return "#FF0000";
  } else {
    return "lightblue";
  }
}

const w = 1603;
const h = 540;
const padding = 150;

const title = d3
  .select("main")
  .append("h1")
  .attr("id", "title")
  .text("Monthly Global Land-Surface Temperature");

const subtitle = d3
  .select("main")
  .append("h4")
  .attr("id", "description")
  .text("1753 - 2015: base temperature 8.66℃");

const svg = d3.select("main").append("svg").attr("width", w).attr("height", h);

const url =
  "https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/global-temperature.json";

const months = []

document.addEventListener("DOMContentLoaded", function () {
  fetch(url)
    .then((response) => response.json())
    .then((data) => {
      const dataset = data.monthlyVariance.map(function (item) {
        months.push(new Date(`1700-${item.month}-01`))
        return {
          year: new Date(`${item.year}-${item.month}-01`),  
          month: new Date(`1700-${item.month}-01`),
          variance: item.variance,
          actualTemp: 8.66 + item.variance,
          colorHex: calculateHex(8.66 + item.variance)
        };
      });

      console.log(dataset);

      const minYears = d3.min(dataset, (d) => d.year);

      const maxYears = d3.max(dataset, (d) => d.year);

      const minMonth = d3.min(dataset, (d) => d.month);

      const maxMonth = d3.max(dataset, (d) => d.month);

      console.log(minYears, maxYears, minMonth, maxMonth);
      
      
    
      const yScale = d3
        .scaleBand()
        .domain(months)
        .range([h - padding, padding]);

      const xScale = d3
        .scaleTime()
        .domain([new Date("1752-01-01"), new Date("2016-01-01")])
        .range([padding, w - padding]);

      const yAxis = d3.axisLeft(yScale).tickFormat(d3.timeFormat("%B"));

      const xAxis = d3.axisBottom(xScale).tickFormat(d3.timeFormat("%Y"));

      svg
        .append("g")
        .attr("id", "x-axis")
        .attr("transform", `translate(0,${h - padding})`)
        .call(xAxis);

      svg
        .append("g")
        .attr("id", "y-axis")
        .attr("transform", `translate(${padding},0)`)
        .call(yAxis);

      svg
        .selectAll("rect")
        .data(dataset)
        .enter()
        .append("rect")
        .attr("x", (d, i) => xScale(d.year))
        .attr("y", (d, i) => yScale(d.month))
        .attr("width", 5)
        .attr("height",20)
        .attr("data-month", (d) => d.month)
        .attr("data-year", (d) => d.year)
        .attr("data-temp", (d) => d.actualTemp)
        .attr("class", "cell")
        .style("fill", (d) => d.colorHex);
    });
});

Forget the tooltip\legend tests which I didn’t start to work on yet, I’m still failing test #8. and #9.

Hola.

@ emibonezzi

No se si por el idioma sea dificil entender lo que te digo, una disculpa por eso, pero no me siento comodo escribiendo en ingles.

El primer codigo que compartiste solo requeria ligeros ajustes para cumplir con las pruebas, el que tienes ahora tiene muchos defectos, pero el mas importante esta aqui:

.then((data) => {
      const dataset = data.monthlyVariance.map(function (item) {
        months.push(new Date(`1700-${item.month}-01`))
        return {
          year: new Date(`${item.year}-${item.month}-01`),  
          month: new Date(`1700-${item.month}-01`),
          variance: item.variance,
          actualTemp: 8.66 + item.variance,
          colorHex: calculateHex(8.66 + item.variance)
        };
      });

Estos valores -01 afectaran todo el codigo, como los tenias estaban bien, lo que te mencione de restar 1 era solo en la linea que te marque, y eso era porque tenias este array .domain([12,11,10,9,8,7,6,5,4,3,2,1]) y son cosas del famoso indice 0, entonces habia dos soluciones:

1.- .domain([11,10,9,8,7,6,5,4,3,2,1,0])

2.- .attr("data-month", (d) => d.month - 1)

Solo debes aplicar una opcion.

Lo del otro problema tambien era facil de resolver.

Te recomiendo regresar al anterior y desde ese punto puedo seguirte ayudando a resolver los problemas que tienes.

saludos

2 Likes

Gracias mi amigo. Volví a mi código original, implementé su edición más analicé el tiempo y aquí estamos. Prueba aprobada. ¡Excelente!

import * as d3 from "https://cdn.skypack.dev/d3@7.8.2";

function getMonthName(monthNumber) {
      return new Date('1999-' + monthNumber + '-15').toLocaleString('en-us', { month: 'long' })
    }

function getYear(y) {
  return new Date(y + "-01-01").toLocaleString('en-us', { year: 'numeric' })
}

function calculateHex(v) {
  if (v >= 2.8 && v <= 5.0) {
    return "#008080";
  } else if (v > 5.0 && v <= 7.2) {
    return "#FFFF00";
  } else if (v > 7.2 && v <= 9.5) {
    return "#FFA500";
  } else if (v > 9.5 && v <= 12.8) {
    return "#FF0000";
  } else {
    return "lightblue";
  }
}

const w = 1603;
const h = 540;
const padding = 150;

const title = d3
  .select("main")
  .append("h1")
  .attr("id", "title")
  .text("Monthly Global Land-Surface Temperature");

const subtitle = d3
  .select("main")
  .append("h4")
  .attr("id", "description")
  .text("1753 - 2015: base temperature 8.66℃");

const svg = d3.select("main").append("svg").attr("width", w).attr("height", h);

const url =
  "https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/global-temperature.json";

document.addEventListener("DOMContentLoaded", function () {
  fetch(url)
    .then((response) => response.json())
    .then((data) => {
      const dataset = data.monthlyVariance.map(function (item) {
        return {
          year: item.year,
          month: item.month,
          variance: item.variance,
          actualTemp: 8.66 + item.variance,
          colorHex: calculateHex(8.66 + item.variance)
        };
      });

      console.log(dataset);

      const minYears = d3.min(dataset, (d) => d.year);

      const maxYears = d3.max(dataset, (d) => d.year);

      const minMonth = d3.min(dataset, (d) => d.month);

      const maxMonth = d3.max(dataset, (d) => d.month);

      console.log(minYears, maxYears, minMonth, maxMonth);

      const yScale = d3
        .scaleBand()
        .domain([11,10,9,8,7,6,5,4,3,2,1,0])
        .range([h - padding, padding]);

      const xScale = d3
        .scaleLinear()
        .domain([1752, maxYears])
        .range([padding, w - padding]);

      const yAxis = d3.axisLeft(yScale).tickFormat(x => getMonthName(x+1));

      const xAxis = d3.axisBottom(xScale).tickFormat(x => getYear(x));

      svg
        .append("g")
        .attr("id", "x-axis")
        .attr("transform", `translate(0,${h - padding})`)
        .call(xAxis);

      svg
        .append("g")
        .attr("id", "y-axis")
        .attr("transform", `translate(${padding},0)`)
        .call(yAxis);

      svg
        .selectAll("rect")
        .data(dataset)
        .enter()
        .append("rect")
        .attr("x", (d, i) => xScale(d.year))
        .attr("y", (d, i) => yScale(d.month-1))
        .attr("width", 5)
        .attr("height",20)
        .attr("data-month", (d) => d.month-1)
        .attr("data-year", (d) => d.year)
        .attr("data-temp", (d) => d.actualTemp)
        .attr("class", "cell")
        .style("fill", (d) => d.colorHex);
    });
});

Hola

@ emibonezzi

Perfecto,

Una ultima sugerencia, si cambias esto:

.domain([1752, maxYears])

Por esto,

.domain([minYears, maxYears])

Tambien funciona, y aunque no es el caso, si los datos cambiaran se adaptaria a los nuevos datos.

saludos

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.