Check out a free preview of the full Data Visualization for React Developers course:
The "Going from Data to SVG Solution, Part 1" Lesson is part of the full, Data Visualization for React Developers course featured in this preview video. Here's what you'd learn in this lesson:

Shirley walks through the solution for Going from Data to SVG Exercise using D3's extent(), scaleTime(), scaleLinear(), and map() functions to map temperature data to a visual representation. - NOTE: Remove "ask for questions" remark by Shirley. - https://github.com/d3/d3-array#extent - https://github.com/d3/d3-scale#scaleTime - https://github.com/d3/d3-scale#scaleLinear

Get Unlimited Access Now

Transcript from the "Going from Data to SVG Solution, Part 1" Lesson

[00:00:00]
>> Shirley Wu: For this example, what we want to do is take this data, use the date, map the date to the x position using time scale. And I made a tiny little change earlier during the break, which is use the high temperature to map to the y position using the linear scale.

[00:00:27] And calculate the height of each of the bars as the difference between the high and low temperatures, with an Asterisk. And then using all of those, return an array of object where each object has x, y, and height attributes that will be mapped to the SVG rectangle elements and their attributes.

[00:00:52] So let's go through this together, and let's, while we're going through it, console.log a bunch of things. So we can get, hopefully, an intuitive understanding of how all of this works. So the very first thing I wanna do is I want to map the date to the exposition.

[00:01:12] And so, the very first thing we need to do is get the min and max. Let me make this bigger. So get min and max of the date, so to do that I just sent to use extent d3.extent and I pass in my data array and I give it an accessor.

[00:01:39] So basically, telling d3 that for every while we're looping through the data, get the date of each object and then give me back the minimum date and maximum date.
>> Shirley Wu: And I'm going to console.log my extent, shift enter, and then you'll see it's a minimum, where the minimum is January 1st.

[00:02:06] It's an array. Where the minimum, the first one is January 1st and the second one is December 31st. And that's the minimum and maximum of your date. That's super simple in d3, to get the min and max. And then, we want to pass the minimum and maximum into the time scale that we create.

[00:02:33] So xScale, and I tend to call it whatever the screen space thing is going to be, so xScale = d3. And it we said, let's use a time scale, so d3.scaleTime pass in the domain that we just calculated and the range. And we want the range to be the minimum, the January 1st, we wanted to be at positions 0.

[00:03:11]
>> Shirley Wu: And then, we want the December 31st to be whatever our width is and I've defined our width as 650.
>> Shirley Wu: So that's the xScale. And now let's take a look at so I think was it Derek that noticed that if you could just console log the xScale it's just a function.

[00:03:35] So this is a function that takes in you want to pass in, in this case you want to pass in a date object. Because you've defined it as scaled time. So you want to pass in, let's just try passing in for example,
>> Shirley Wu: Let's start with January 1st, 2017.

[00:03:59] Let me clear this.
>> Shirley Wu: Look, it gives me back a 0. And which is just exactly as we expect. Let's try February 1st, which is apparently 55.35, so that's gonna be our x position, it's gonna be our pixels. And then, if we do June 1st it's at 269 pixels.

[00:04:23] And if we do December 31st, wait, that's not 31st. December 31st, it's at 650 pixels. Super useful, because imagine having to calculate yourself and going between dates to expositions. Imagine having to do this yourself. I feel like that would be half my day right there. But makes it really really easy for you.

[00:04:50] So that's the xScale. That's all good, then let's calculate the same thing for the y, so I am just gonna call it yExtent, cuz I already used extent there. And I am gonna do the exact same thing but this time. So this I am trying to do with map, I'm trying to map the high temperature to the y position.

[00:05:15] So get the min/max of the high temperature. So exactly the same code as above, d.high. So I'm telling d3, hey, loop through my data object, access the high temperature, the high attribute, and give me back the min and max of that. And let me console log that.
>> Shirley Wu: And the min and max of my high temperature is 49 and 104.

[00:05:54]
>> Shirley Wu: And again, we want to create a scale. This time, a yScale, d3.scaleLinear(). Again, pass in this extent. This 49 to 104 and I want to map the 49 degrees. I want to map that because it's going to be lowered down on the screen, I want to map that to what I define as height and I define height up here as 400 pixels.

[00:06:27] So I basically want to map the 49 degrees to 400 pixels down on the screen, and I want to map my 104, my highest temperature to the highest part of my screen which would be 0 pixels in the y coordinate. And then now if we console.log, let's say we want to look at how much 49 degrees is and it's of 400 pixels.

[00:07:02] Let's say, I'm curious about 70 degrees that's I wait, let me stop console log in extend and that's at 247 pixels. And then for 104 degrees, that's at 0 pixels in the y axis. So that's why, so that's the scales.
>> Speaker 2: What's the difference between scale time and scaling here, are they the same?

[00:07:30] Can you use either one?
>> Shirley Wu: Yes, that's a great question. So they're similar in that they both take continuous domains and they output continuous ranges. But the only difference is that with scale time, it specifically takes in JavaScript date objects. And scale linear takes in integers and numbers or numbers, yeah.

[00:07:54] So yeah, they both output numbers though. That's a great question.
>> Speaker 2: Do you have to use a date object or you could use like a Unix time stamp like a string.
>> Shirley Wu: For scale time I believe it has to be a date object. But let me double check, because I would think if you do a Unix timestamp you could probably just do linear because it's technically a number.

[00:08:32]
>> Shirley Wu: Scale time that have a temporal domain are course to dates. So I guess if you want to pass in domain by user coarse to dates JavaScript dates, rather than numbers.
>> Shirley Wu: Yeah, and we'll get in to this later on, but scale time is really great for when you want to draw axes.

[00:08:57] Because it will naturally just pull out the months or years to display in the axes where as scale linear if you just did the Unix timestamp, if you ever drew the axes it would just be those numbers and no one wants to see that. So I mean its pretty easy to coarse into JavaScript dates.

[00:09:18] So passing the dates. I think it, yeah, I think its required to be. It looks like its, it looks like it's expecting a date, right? Or maybe it says its coarse dates. Yeah, in general, use JavaScript dates for scale time. Okay, and then we said, that we want to return an array of objects, with each object having x, y, and height attributes.

[00:10:01] Okay, data.map, and we want to loop through the data, and for each data point we want to be, actually even before we do that let's console log and see our data. We have a date object, the average temperature, high temperature and low temperature. And so, using that I want to return for the x position, I want to use the xScale that we defined earlier.

[00:10:39] And I'm going to use d.date and for the y I'm going to use the yScale I use earlier and then for the yScale I used d.high, so this time around I'm also going to use d.high. And for the height I define that as low minus high. And it has to be the y position of the low minus the y position of the high.

[00:11:08] It can't just be low minus high, the temperatures themselves, cause then that wouldn't be the right height, it has to be the y position of the low minus the y position of the highs, so we're gonna do the yScale(d.low), minus yScale(d.high). And so,
>> Shirley Wu: if we just do that

[00:11:30]
>> Shirley Wu: We'll see that for each of the objects we have the x position, the y position and the height calculated.
>> Shirley Wu: And we'll see right here our black bars, actually, let me keep with the code, and then you can see the black bars yourselves. If you don't write all of this down, I have the full code.

[00:11:58] If you go into my slides where it says full notebook, it has all of the code there, so you can go back and take a look at it, but don't look ahead in the full one or else it defeats the point of the exercises. But yeah, even if you don't have it all written down, it's going to be okay.

[00:12:17] Yeah, is there any part of this that you want me to explain in more detail, explain in a different way. I just want to make sure all of this stick intuitively in your heads, because I think these are some of the most important parts of d3 that you probably be using over and over again when you're building charts whether with react or not.

[00:12:40]
>> Speaker 3: Can you talk about how you're getting the height?
>> Shirley Wu: Yes, so let's actually console log that. So let's do it this way. So this right here, this yExtent is the min and max of the height, right? So let's just together do this exercise. Let's get the min max of the, do you mean like how I'm getting it or why I'm doing it that way?

[00:13:14]
>> Speaker 3: Why you're doing it that way.
>> Shirley Wu: Okay, so let's do the min and max of the high temp and then a min and max of the low temp
>> Shirley Wu: So let's say highExtent = d3.extent(data d.high). And then, same thing is equal to d3.extent(data d.low)
>> Shirley Wu: And you'll see, hopefully, once I console log these.

[00:13:59] And this you don't have to copy down, this I just want to show. Okay, so here you'll see that for, let me make this easier to read. And so you'll see that for the high temperatures, the min is 49 and the max is 104, and the low the min is 11 and the maximum is 72.

[00:14:24] So this is the min and max of these two temperatures throughout the whole year. And the reason why I'm, I think there's probably two part to that, two answers, two parts of the answer to that question. The first part is I'm guessing why not, cuz I made it sound like in my instructions to subtract the low from the high, right?

[00:14:47] So why not just subtract this number from this number or this number from this number. And that's because this is the raw data, whereas the height that we want is the, let me try and figure out how to talk about this. So first of all, if we subtract the low from the high, that would be 11 minus 49 and it would be a negative number.

[00:15:17] And widths and heights don't take negative numbers. That's one, but the more important part is that when we talk about height, it's the height of the bar, the height of the bar in the screen space. So then we want to be subtracting screen spaces or basically coordinates.
>> Speaker 2: The location on the graph-

[00:15:39]
>> Shirley Wu: Yes, thank you.
>> Speaker 2: Actual data points, okay.
>> Shirley Wu: Thank you so much.
>> Speaker 2: I understand.
>> Shirley Wu: Yeah, location of the graph, location in the screen. And that's why we can't, actually, we can probably do this. No, we can't do that, never mind. We can't do a d.low- d.high and then do the yScale.

[00:15:58] We have to first get the location of the lower temperature and then subtract that from the location of the higher temperature. And it's also very specifically has to be the low minus the high because the low is further down on the screen and the high is higher up in the screen.

[00:16:20] So that's why those two parts, y has to be converted to yScale both of them have to be converted to yScale. That's also the reason for the order of which one gets subtracted. Yeah, thank you so much for letting me make that clarification. And then, let's look up this.

[00:16:43] You might actually see something that's unexpected, which is that the lower some of the lower temperatures are going of the screen and that makes sense. Because we defined our domain, so if we take a look at our yScale we told it hey, map the minimum of the high to the bottom.

[00:17:09] But if you notice, the minimum of the height is 49 degrees, but then there are some temperatures, low temperatures, that are lower than that. The lowest for the low temperatures are 11. And that's why it's going below the screen, sorry, below. And remember earlier when we were talking about viewports and how I think of SVG as just like we draw like the outside world is where we draw the shapes and then the SVG is just basically a window into that?

[00:17:39] So we've basically drawn all of these bars, but some of them just go below our window. And so, to fix that, we actually need to say something along the lines of, okay, so we don’t want the range, we don’t want the range to be mapped from 49 to 104, we actually want it to be, let's say, min, max, and we want it to be from, we actually want something like this.

[00:18:23] So for the minimum, I want it to be either 0 if this number is above 0, I want the minimum to be 0, and if this number is negative, I want it to be that number. And that way.
>> Shirley Wu: We can have all of our bars fit in to the SVG window.