everyone thanks so much for coming out
today I'm gonna walk you guys through a
quick exercise with d3 d3 is a
JavaScript library so it isn't a
language itself it's actually using
native JavaScript it was all built by
one human being he's a very cool guy who
was really good at this and his whole
idea was that he wanted to put together
a library that would in relatively few
lines of code give you the ability to
make really interesting interactive and
adaptable data visualizations so a lot
of what we're going to be dealing with
today is what it's like to loading data
what it's like to do that synchronously
versus asynchronously and then we're
going to build a pretty simple bar graph
here where we're gonna have some
clicking capability and all of this is
being generated dynamically so I'm gonna
step you guys through the code so you
have an idea of what this looks like
feel free to stop me at any point but a
few things that I do want to mention
right off the bat is that in order to
get any of this to work you are going to
need a web server up and running so just
keep that in mind the whole reason that
any of this is running is because I have
a terminal window here where I've
already like typed in an HTTP server and
this is all running good to go before
before I start looking at code awesome
great so first thing first is we're
going to talk about index.html you don't
have to do this in index.html since this
is a pretty simple website with only one
page I decided to put it in index but
you could of course have data
visualizations on any of your website
pages so we're gonna have some typical
boilerplate code here where we see
things like the meta charset the meta
names the title and then immediately I
start including things like bootstrap
CSS which I use a little bit of here
I've made an API call to Google to get
some fancy fonts this is absolutely not
d3 related and then I've included some
of my own style sheets these are normal
things you can do you don't have to do
have absolutely nothing to do with d3
itself it's more of the stuff that we do
in the body and that we include at the
bottom of the body that is actually d3
specific we're even here I've just sort
of configured the pay
so that I have a div for my header and
then I have a div where most of my
visualizations and most of the
interesting components of this page are
going to exist so let's talk about that
a little bit I'm using the bootstrap
container class here which basically
lets me resize as I would like to so if
you ever like click and drag the the web
page your data visualizations will
resize accordingly so you don't end up
with things that are like awkwardly cut
off or that start to look a little bit
weird this is more of an aesthetic
choice as opposed to a functional choice
but it ends up being a nice way to do
this and when you're using anything
within the container the next class that
you have to have as a row if you're ever
interested in looking any of this up you
can google bootstrap grid layout and
you'll immediately get documentation for
this and what's important to know about
the grid layout is that the web page is
split into twelve columns so you'll see
here that I actually have two divs each
taking up six columns this is really
just so that I could get a nice effect
of splitting the page in half between
the data visualization itself and any of
the information that I was going to show
you could absolutely configure this
differently you could have your data
visualization take up the entire width
of the screen you could have a take up
considerably less of the screen but for
my purposes this is what I would I
wanted to do and what I really want to
point out is that I have made very
judicious use of IDs here we're within
d3 we're going to have the capability to
similar to native JavaScript actually
select components out of the the Dom out
of the document object model and the
easiest way to do that is in fact to do
it by ID so get very accustomed to using
IDs and try to keep in mind that the IDS
that you use should be descriptive
enough that you know you either don't
forget them or when you're actually
writing your JavaScript it's easy enough
to know what you're actually referring
to within the HTML itself so you'll
notice here I actually have two columns
that are happening one where I've said
okay I'm going to actually display the
chart and one where I'm going to display
the information and within the
information I said okay I'm going to
have a header and then I have this other
div that I've said is going to be albums
the other really important thing here
that is now actually d3 specific is that
I need to be sure to include the d3
JavaScript library if I don't include
this we literally aren't working with d3
at this point in order to find this file
you can literally just google d3
JavaScript and you will find a link in
order to include it in a script tag I
always highly recommend whenever you can
following that link that you would
otherwise just include and actually
copying and pasting all of that source
code into a file because that way you
never have to deal with latency if your
connection is slow and now your
JavaScript libraries aren't running so
in fact this file exists natively within
my directory here so that I don't have
to deal with any of these issues of you
know poor connection and now my
visualizations aren't running and you
know of course I have my bootstrap j/s
I'm gonna use a little bit of jQuery
which I think you all saw in one of the
most recent p-sets
I'll point it out but it's really a very
small use and then finally I'm going to
use cue which is just another JavaScript
library and the whole purpose of this is
to make sure that my data gets loaded
properly so having looked now at the
JavaScript itself I've also included one
more javascript file which is the file
that I've actually written and where any
of the logic that I have done for my
project will actually exist for your
projects they might be a little more
complicated where in fact you might have
several JavaScript files that are all
interacting with each other always be
sure that you're including your
JavaScript files it's one of my favorite
debugging stories where I'm like wow
I've written all of this code nothing is
working nothing is showing up why isn't
it showing up and it's because I've
forgotten to include the file so it's
always good to keep this mental
checklist of like have I included the
files that I need to include so if we
hop over to main dot j s first thing I
really want to talk about is this idea
of asynchronous JavaScript loading where
in fact I'm going to be loading datasets
that again exist natively on my computer
and just to give you guys a quick idea
of what those look like
oh goodness well here we can actually
open them up over here
so you'll see I have two datasets here
I'm just gonna go ahead and open the
artists dataset so all of this code are
all of this data rather is coming out of
the sequel lecture so some of it should
look vaguely familiar because it came
out of the sequel lecture I actually
ended up having to treat my data a
little bit differently to make things
line up properly you'll remember that in
the sequel lecture David was talking
about ways to make your database more
efficient and as a result rather than
store an artist name he would instead
just store an integer representing an
artist ID which is a perfectly valid way
to do this and it was actually a very
good opportunity for me to show you guys
how to use multiple data sets that
actually perhaps interact with each
other but this is just one of the two
data sets you'll notice that I've saved
it in a CSV format this was out of
convenience more than anything you could
absolutely separate save it as a
like tab separated values which is
similar to a CSV but uses tabs as two
limiters just be consistent with what
you're using and keep in mind that
whatever type you use to save your data
is going to correspond directly to the
methods that you're going to be using to
actually load that data so if we look at
this step here this is probably one of
the most important steps that we're
going to have where in essence I've said
okay for each one of these data sets I
want you to call d3 CSV on it what de 3
dot CSV actually does is it calls a
method that literally reads in your CSV
and saves it as an array of JavaScript
objects where each one of the objects
and I'll show this to you in the
developer tools in chrome in a second
but each one of the objects is going to
have a key that is artist ID and a key
that is artists and so each one of these
lines here is going to turn into its own
JavaScript object so that's kind of the
direct the direct mapping that's
happening there so I've said okay for
each data set please load it in and it's
kind of this defer that is most
interesting where we've said once you
load this one in wait to do anything
else but please also load in the next
one and finally this a weight line is
the most
where we've said okay once both of these
two first statements are done meaning
once you've loaded in both of those
datasets now please call this other
function and what ends up happening here
is this was just a function that I wrote
you could have done this as an anonymous
function but it would start to get
pretty ugly pretty quickly and so I went
ahead and just gave it a name
for simplicity's sake but what Q ends up
doing and Q is coming out of this Q
JavaScript library it says okay whatever
function you pass to a weight needs to
take at least one argument but it's
going to be one plus however many defers
you have so you'll notice here that
artist dot CSV is going to immediately
give us artist data I could have called
this whatever I wanted I could have
called it foo I could have called it
llama it's just most convenient here to
call it artist data so that it is clear
what I've actually loaded in and here
I've called this Alba because I was lazy
and didn't want to type album but I
could have easily done that the order
here matters right ii defer is going to
correspond to this third argument here
this first error is an error that
potentially might be thrown by either
one of these two functions right either
one of these two calls to d3 csv if for
example something was wrong in opening
your csv file or if it wasn't able to
get through the whole file it will
actually return an error and so the
first thing you want to do is make sure
that you have actually checked the error
if that error exists we're gonna go
ahead and return as opposed to just
console log we're returning here so that
the entire program does not continue
running but we're gonna console.log the
error so that we as developers can try
to troubleshoot exactly what happened
but assuming that that didn't happen
let's step through the rest of the code
so the first thing i said is okay i i'm
immediately i'm going to have a problem
because my datasets don't make a lot of
sense and in fact what i'm going to do
here is i'm going to go ahead and
comment in this console log which is
going to show us everything that's in
album data and i'm going to go ahead and
put in another console log which is
going to show us artist
this is a cute trick this is the printf
debugging of JavaScript I highly
recommend using it nothing is more
frustrating than not knowing what your
data looks like because it's done hard
to make logic to manipulate your data so
the first thing I always like to do is
actually figure out what does my data
look like so I always console.log my
data as soon as I've loaded it in so in
fact if I save this and make sure that
my server is still running I go back
over here refresh this page and then I'm
going to go ahead and hope that the
Internet is working and in fact you see
right away that I have an error so this
is why the console is super helpful
first things first is just understanding
how to read what the console errors are
telling you you'll see here the line
where the error occurred so I I know I
should be looking at main J s line 22
where it has said to me okay you've
referred to something called album data
and it's not defined so in fact if I go
back to line 22 I can immediately say oh
yeah I didn't call it album data I
called it a loop data right I can go
back save it
refresh the page again and you'll notice
that if you have no errors things will
load if you have errors things will not
load so this is always a good thing to
do so these two things here are actually
coming immediately out of those console
log statements that I did and in fact
let me make this a little bit bigger for
us so album data we see that it has
three hundred and forty-seven items
remember I mentioned that it was an
array of JavaScript objects one way you
can immediately see that is that this
first bracket here is in fact a square
bracket right this tells me that it's an
array similar to an array in Python or
list in Python or an Iranian see if you
click this little drop down arrow it
does this nice thing where it segments
it for you because otherwise it gets
kind of impossible to read and to see
you can drop down again and you can
immediately see okay this is what my
data looks like great each one of these
objects has this album ID key and has
this title key has this artist ID key
alright this will be good for me to know
as I'm writing loops to iterate through
this data by the same token I can look
at the artists data
and I can say okay artists data all has
an ID and it has an artist that it
corresponds to I happen to know from the
data that I loaded in that an artist ID
of one here corresponds to a same artist
ID of one over here right so for those
about to rock we salute you I know that
this is supposed to be an ac/dc song or
ac/dc album right so keeping that in
mind I said to myself okay what would be
an interesting thing to visualize once
you've loaded in your data and once
you've decided what your data should be
the next question you should really be
asking is what am I trying to visualize
because that's going to dictate how
you're going to run through your your
code and so what I decided to visualize
was actually just the number of albums
that were produced by a particular
artist so you notice here on my y-axis
I've got just a number of albums and on
my x-axis I actually have the name of
the artist that this corresponds to I've
added a little bit of extra
functionality that if you click on any
of the bars you can actually see a list
of these albums and we'll talk about
that in a second but keeping that in
mind I said to myself okay I'm gonna
need some way to count the number of
times an artist ID occurs given the
number of albums right so the first
thing I said to myself is okay I'm going
to need to make some kind of mapping
between an artist ID and the actual name
of the artist so what I did was I did
the following I said okay I'm going to
make an artist map which is itself going
to be just a JavaScript object or you
can think of this more like a dictionary
which is kind of how I was envisioning
it as I wrote this code and the idea
here is that we're going to iterate
through all of the artists data and for
each one of the JavaScript objects in
the artist data right so for each object
that has an artist ID and it has an
artist name we're going to say okay
here's that individual object and we're
going to say okay within artists map at
the index that corresponds to that ID
please save the name of that artist and
this was just to make a quick easy
mapping so that I could refer to these
objects later the more interesting stuff
actually happens in this d3 nest
so what DNS does is that it says to you
okay I'm going to iterate all through
all of this data for you
what I'm going to do is I am going to
build a brand new object where the keys
or gorse are going to correspond to
something that already came out of your
data and the values or the leaves as
they like to call it are going to
correspond to something else out of your
data so what I've said here is okay
I want account by artist ID and the
reason I wanted account by artist ID was
because I had already made this mapping
by artist ID so that I could easily
index into it so I said okay for each
one of the pieces of data within my
album data so this entries actually
tells you which data you're going to be
iterating through I've said okay the key
is going is going to correspond to that
particular objects artist ID I've then
said okay I want you to roll up all of
the leaves I think this is one of the
most confusing lines in this code so let
me just unpack it a little bit for you
and I've left a code
I've left a comment just to be a little
more clear but what we're basically
saying here is what roll-up does is that
it searches through every single one of
the items in your greater data set and
it finds the ones that match the
particular key so in fact what leaves is
if I were to console dot log it leaves
is actually an array of objects that
match that key you can see then why that
would be helpful for me because what I'm
really trying to do is count the number
of objects that correspond to a
particular artist ID
therefore by getting the length of that
array which is literally the number of
objects that have that artist ID this is
how I've gone through and actually
counted how many things exist for this
artist the real question here is Athena
was this the only way to do it and the
answer to that is no in fact with d3
there's a lot of ways that you can do a
lot of the same operations but in fact
this is probably the most concise way to
do it albeit maybe a little bit unclear
if you're just using it for the first
time that being said d3 actually has
very good documentation and so if on
your computer now you were to google d3
best example if you see anything from BL
dot Ock something like that
I look at it and I read
locks if you see anything from like
blocks org that's great examples of
visualizations that people have done
that use different functionality out of
d3 I highly recommend taking a look at
it so now I have this count by artist ID
and I've said to myself great I have all
of this information and I've said all
right I probably want to make a bar
graph and because I want to make a bar
graph what's important to me is to make
sure that my data is arranged in such a
way that it's going to be easy to
display it so in fact the next thing
that I do is an in-place sort in place
here meaning that I actually call this
function on this this array that I've
been given and it will sort it in place
for me the way sort works is as follows
sort expects an anonymous function and
in fact what source hands that anonymous
function is to side by side objects so
we have object a and object B it could
be that object a is greater than object
to B but in order to sort things in
ascending order what you really want is
the difference between object a and
object B but keep in mind that object a
really is an object and as a result it
has multiple keys the thing that I was
interested in here was value and the
reason I knew it was value so for
example like let's say I didn't know
what I was going to get out of this
count by artist ID I could go ahead and
say okay I'm gonna console dot log it
right
and this is just a cute trick I like to
use for console.log where you can
actually label the thing that you're
about to log so that you can find it
easily in the console so I can go ahead
and save go ahead and refresh and I can
say okay like what did I get back okay
so here it is this artist ID count I can
see immediately again that this first
character here was a bracket so I know
it's gonna be an array and I can see
that what I end up with is a bunch of
objects where they have the key key and
the other key value where value is
actually the number of objects that were
counted for this particular artist ID
this was the only way for me to know
that when I was sorting I should be
looking at the value field and not some
other field I literally had to pull up
the data and look at it in order to
figure this out
there is nothing wrong with doing that
and in fact I encourage you to do that
so once I went ahead and sorted I said
okay just for like display purposes here
I'm actually going to cut down some of
the data we had because we had like 204
items of data and that just like gets a
little bit ugly to display there are
ways to get around this but just like to
make this a tractable example I said
okay I'm gonna just get rid of
everything from index 0 to index 180
this was perfectly arbitrary you
absolutely don't have to do this but it
just simplified a little bit of this
process and then finally what I said was
ok now that I have loaded all of my data
and now that I have cleaned my data in a
way that I'm happy with I can go ahead
and call a new function that is actually
going to create the visualization it's
really important that you never try to
create the visualization before you've
loaded all of your data because in fact
the way JavaScript works is that it
might try to create your visualization
before your data has finished loading as
a result if your data doesn't yet exist
your visualization is going to fail and
if it fails you might have to refresh
the page several hundred times until you
get lucky that maybe your data loads
first and loads fast enough so in fact
you'll notice here that I never try to
say ok create the visualization until
I've made sure that everything has been
loaded in this is super important easier
ways to do this
include actually just calling d3 CSV and
within that pass it an anonymous
function and then do all of your data
creation within d3 CSV we can look at an
example of that later if that's
confusing but this is just one way that
you can do it so now I'm actually going
to talk about the visualization itself
but before I move on any questions yeah
yeah so the question here was just to
give another quick example of how D 3
nest works so D 3 nest is going to say
I'm going to build you a new array of
objects and the array of objects that
I'm going to give you is going to have a
key and it's going to have a value it
wants to know as it's searching through
your data what key do I want to be
matching against and so what it does is
it says ok as I'm iterating through your
data I'm going to look at a particular
datum and I am going to get its artist
ID and that is what I'm going to use as
the key here right roll-up is kind of a
confusing part where roll-up kind of
does this like search and count for you
where it says ok I'm holding this key
let's say the key is 3 and it's going to
look through every single one of the
objects within this album data right and
it's going to say does this object match
this key if yes I'm going to stick it
into an array does this object match if
no I'm gonna discard it does this one
match yes no yes no and so at the end of
the day what roll-up actually passes to
this function is an array of all of the
objects that matched that key another
way to think of this is that each one of
these album data actually had an artist
ID right so if this artist ID matched
the current key that I was holding this
would be considered a match once I have
that array I can do whatever I want with
that array but because what I am
interested in is actually the count I
know that by taking the length of the
array that is really the same as saying
how many albums correspond to
artist and this final thing here the
order I always think is a little bit
weird but entries is actually where you
specify the data set that you want to
iterate through did that answer your
question
great anything else before I move on
okay great
all right let's talk about the
visualization so there are fancier ways
to do visualizations and less fancy ways
I always like to start by initializing a
margin object where you'll notice that
there's actually like a nice little bit
of space here along the side and there's
some space over here and like admittedly
this name was the world's longest artist
name and so it is taking up more space
than it should be but there's actually a
little bit of space where and you can
actually see that my visualization
exists within this nice confined
rectangle the way I've configured that
is through this margin object where I
can now like calculate the width and the
size of my actual visualization itself
by just changing values in one place as
opposed to changing values in a bunch of
different places so this was really more
of a convenience thing more than
anything but I highly recommend using it
so this is the little bit of jQuery that
I said I would point out to you guys
we're in essence I've said okay I don't
want to hard-code the width and the
height of my visualization in fact I
want my visualization to conform to
whatever the width and the height of the
element that it exists in is so that's a
fancy way of saying if I've already said
that I'm going to put my visualization
in a box that is 500 by 600 pixels I'm
once in essence what I want to happen
here is this width to equal 500 pixels
and this height to equal 600 pixels or
the other way around quite remember
which way I said it and in order to do
that I've said okay jQuery please get me
the HTML element that matches this ID
where notice that I've actually passed
parent element in here
so you actually it's worth noting that
this create viz could be used multiple
times depending on the data that I'm
going to pass so that's worth noting but
notice that I've said okay
this visualization is going to exist in
the chart display column which you'll
remember was the ID of this particular
div here all right so this is why IDs
we're gonna be super important all right
so please get me the width of that and
then go ahead and subtract this margin
that I've gotten you both for the left
on the right where we said okay I know
that this full width is going to be this
whole box in fact I want to constrain
things a little bit in case my
visualization has like straggling items
because I don't want those to end up
either off of the screen or out of the
parent element so it's absolutely worth
subtracting margins here and you do the
same thing for the height the other
thing worth noting here is SVG's if you
ever start reading about d3 you're going
to see this all over the place SVG
stands for scalable vector graphics
which is really just a fancy way of
saying that a bunch of people got
together and said yeah graphics on the
Internet are really hard because the
minute you try to rescale them they lose
all of their resolution let's build
something that isn't going to lose its
resolution no matter how big or how
small you've made it and that is exactly
what an SVG is d3 expects SVG's it will
only ever append objects to SVG's and so
as a result the first thing you will
always find yourself doing whenever you
deal with d3 is you will find yourself
making what you can think of as the
canvas SVG this is the SVG onto which
all of your particular objects that
actually build up your visualization are
going to end up so if we look at this
this d3 dot select is really analogous
to our document dot query selector or
we've said okay with d3
go ahead and find me the parent element
and the first thing that I want you to
do is actually append to it an SVG and
we'll look at the what the HTML looks
like for this in a second we're now d3
really just likes chaining syntax where
we said okay get me the parent element
and append an SVG to it from this point
they'll like pointer that I'm holding
corresponds not to the parent element
but actually to the SVG itself and I
said okay for this SVG that I'm holding
please give it the attribute of width
and I've given a calculation for the
width please give it the attribute of
kite I've given a calculation for height
and then append to it this thing called
a G group a G group is really just a
nicer way in d3 to start building layers
on top of layers so that if you want to
for example apply styling to a bunch of
things if they're all on the same layer
you can apply the styling very easily
you could absolutely have done this
without using a G group but this was
more is it kind of just like the rule of
thumb that people like to use and
finally what I've said is okay once
you've appended this SVG go ahead and
transform it which is really the same as
saying okay I'm going to actually shift
it somewhere on the page and the shift
that I want to do is a horizontal and a
vertical translate where I've said okay
translate it a little bit to the left
this many for actually rather translate
it to the right this many pixels so that
I get my margin and translate it down
this many pixels okay all right question
on SVG you don't have to understand what
it is as long as you understand that
it's a canvas at the end of the day
that's all this is where if you think
about it this white block here you can't
actually see but is basically my SVG and
everything that I've appended to it are
just other elements that I have put onto
that canvas if that canvas wasn't there
I couldn't have put any of these
elements on here the next thing you
should notice is that really a bar graph
is just a bunch of rectangles right and
that is kind of exactly how D 3 is going
to treat visualizations where d3 is
going to say well you know like a line
graph is really just a couple of circles
with a line running through it or a bar
graph is really just a bunch of
rectangles of varying Heights and widths
and so when we are going to be making
this visualization we're going to say
okay I know that I need a bunch of
rectangles and I know that I need them
all to fit right and this is where this
idea of scaling starts to come into play
but scaling is really hard especially if
you don't know off the bat how many
pieces of data you have what the min and
Max values of those data are and like
remember that we didn't hard-code the
width and the height so in fact your
total scale could be changing depending
on what your
element is so d3 has been really nice
and it has actually come up with these
scale generators that let you give it a
few parameters and it will actually
generate the scale for you it takes out
all of the hard thinking so there's
several different kinds of scales that
you can use linear scales are I think
the ones that come most easily to people
because it's literally you know take
this value in this domain and squish it
to fit into the domain of like my width
or my height or the range of my dough of
my height and my width
ordinal scales are a little bit more
tricky in d3 but it's worth knowing how
to use them if you ever want to
visualize something that isn't numeric
where ordinal scales will do the
following ordinal scales will figure out
for you how many items you need to
display it will figure out how wide each
one of those display items need to be so
in this case our bar width and it will
figure out the space that needs to exist
between each of the bars to make all of
this work so you'll notice here that
I've said okay the range of the values
that I need you to output are going to
be from zero to my width and that makes
sense right where I've said this is
going to be the scale for my x-axis and
so I know that my x-axis is going to run
from the zero width pixel to the pixel
representing my width on the other hand
I've said okay between each of the
blocks go ahead and give me half a pixel
worth of padding just to make it look a
little bit prettier I could make this
bigger I could make this smaller this is
really just up to taste and finally it's
the domain that kind of looks a little
bit ugly ranges are the values that the
scale is going to output given a value
and the domain are all of the values
that your scale should expect to get
when it comes to scales the domain is
always going to come from your data
itself so what we end up doing is the
following I've said okay d3 please do me
a favor and apply a function to every
single one of the items in my count data
where the function that I want you to
apply to an individual item is going to
do the following it's going to go ahead
and figure out what the name of that
artist is using my artist map and keep
in mind what I've done here is I've said
okay datum itself is going to be of the
form key
you and I know that the key is going to
correspond to some artists ID knowing
that I can say okay if I give my artist
map an artist ID what it will return to
me is actually the name of the artist so
I've gone ahead and said okay get me all
of the names of the artists that
correspond to all of the data right
that's exactly what this is done and it
has actually built me a Java Script
object but really what I'm interested in
here is all of the possible artist names
that I could have gotten and so by doing
that by asking it okay you're a
JavaScript object please tell me what
all of your keys are I have in essence
said to domain okay here is an array of
every single possible artists name that
you could ever get how it does the math
to figure out which artists name goes
where how wide the bars have to be is
all abstracted away it's not important
for you to know how it does it simply
that it does it quite frankly scales and
axes are some of the hardest parts to
debug in d3 so don't feel bad if those
aren't working quite the way you want
them to right away there's a lot of
really great examples online the linear
scale is a little bit easier where we've
said okay all of the items that you're
going to output are going to be in the
range from the height minus the margin
and all the way to the margin of the top
what's really important to note in terms
of graphics is that in fact while your
height or rather while your width
actually moves in the direction that you
expect it to so like zero starting on
the left hand side and the greater
numbers moving to the right height is a
little bit different in fact the y-axis
is inverted so zero for the y axis
starts in the top left hand corner and
moves down so the greater values are
actually further down within the graphic
why did they do this I'm not totally
sure but it can be a pain as a result
you'll often find yourself reversing
Heights so that the values that you're
getting out are actually corresponding
not to the height itself but the
difference between the height that
you've gotten for a bar and the total
height of the visualization which you
can kind of see is would correspond to
the height of a bar that we would be
thinking of that's the only thing I want
to note I want to note there the other
thing I'll note here is that I needed
the Y scale to know what its maximum
value is going to be and so as a result
d3 gives me a max function which
literally iterates through every single
item in the Count data and it returns
like an array basically of all of the
values and it picks the highest value
could I have done this another way
absolutely but since d3 gives me these
tools you should absolutely use them
okay the scales themselves actually take
care of the math but does not take care
of any of the visuals that you see and
so as a result we actually have to set
up the visuals ourselves again d3 gives
you very easy methods for setting up
axes where if I want an axis on the left
I can literally just call axis left if I
want an access on the bottom I can go
ahead and call access on the bottom
it'll then ask you okay what is the
scaling I should use and the nice thing
is you can actually just pass it the new
scale that you have just made right so
this is quick and easy once you've
figured out the math for the scales the
rest kind of comes naturally so we've
said okay here's an object that is going
to correspond to my axis bottom but it's
not yet on the SVG and this is where we
start to see this first instance of this
method append or append is going to say
okay tell me exactly what I'm going to
append and when I append on that thing
tell me the attributes that it has to
have again by convention we tend to
append axes to G groups the reason we do
this is that if we ever want to add
color to our axes make things smaller on
the axis rotate the axis it's much
easier to do that within a G group than
it is to actually try to find the
pointer to the axis itself once it's
already on the canvas and there's this
important method here specifically for
axes called named call we're in essence
you've said okay I want you to append it
to a G group I want you to give it these
classes so that I can style it later and
now I actually want
you to call this method and make my
access this takes care of everything for
me once you've used this call operator
your axes just magically appear okay
same thing goes for the x-axis where
I've done a little bit of fancier things
one thing I do want to point out is that
in fact everything wanted to start like
a little funky looking where all of the
names of the artists were actually
horizontal and because there were so
many artists it starts to look kind of
ugly right
so d3 is also a lot about like playing
around and figuring out how you can
rotate things and shift things to make
them look pretty so for example if I
wanted all of those artist names to be
rotated 90 degrees from the horizontal
so that they would look perpendicular to
the axis I can go ahead and set this to
90 and so we can see that that looks a
little bit like that I thought that this
looked super ugly and was like hard to
read and I was hoping that this would be
short enough to fit if I rotate it at 75
degrees surprise surprise it was not but
aesthetically I thought that 75 looked a
little bit nicer this is the only reason
I've picked 75 this is purely an
aesthetic choice okay so we've talked
about the axis we've talked about the
scale once you've configured those again
the rest is relatively easy before I
move on to the bars themselves questions
about axes or scales because I think
those are the harder things but if you
have no questions that's also fine
awesome okay far as it is so remember
that I said the d3 kind of likes to
break down what your visualization
actually is and so what these are are
just a bunch of rectangles and so the
thing that I'm actually going to append
to my canvas are really just rectangles
when we're appending let's call them
like visualization items there's this
cycle that d3 likes to use where it's
the like enter update exit cycle where
we've said okay here's the data you're
going to use please enter it this is
sort of this like weird semantic thing
that d3 has adopted but it's very
formulaic and you don't really have to
understand what it's doing as long as
you remember the formula and the formula
is always
here's the data I'm going to give you
now enter into the state where we are
going to manipulate this data so I've
said okay I have this data I'm holding
all of this data and what I'm actually
going to do is I'm going to append the
rectangle so you'll notice here that I
actually have rectangle in two places
select all is actually looking for
pointers to rectangles
even if they don't exist in fact even if
they don't exist you still need to use
select all because what select all will
do is it will actually create pointers
for things that don't exist if your data
calls for that and because I have no
rectangles my data is obviously going to
call for new rectangles to be made so
I'm going to say okay we're going to
append these rectangles and we're gonna
give them some attributes like a class a
fill and then things start to get a
little bit funny where a lot of the
things that we have to think about are
how wide do my rectangles have to be how
tall do my rectangles have to be and
where do I start drawing my rectangles
again d3 and when it comes to graphics
everything seems to do this actually
starts drawing from the top left-hand
corner and so you have to say to
yourself okay if I'm drawing from the
top left-hand corner how far right do I
have to draw this is pretty easy because
this access moves in the direction we
expect it to but how far down I have to
draw remember that all of these values
are actually inverted so when I talk
about width in fact I can just use this
nice little method that comes right out
of my scale where my scale has already
taken into a fact and taken into account
how many bars I'm going to need and what
the spacing between the bars is going to
be and what the total width it has to
work with is and so as a result it can
very easily give me a calculation of how
wide one particular bar has to be and so
I didn't even have to think about this I
could literally just say hey just tell
me what the bandwidth is for a
particular bar great height is the one
that's a little bit funny again because
we have to invert so I've said okay for
every one of the pieces of data that
you're going to get from this data that
I've given you please look at that data
look at its value which remember
corresponds to account here and
going to say okay I need to know what
this is going to be in terms of pixels
in terms of pixels it's going to be
whatever the scale has told me it is and
now I have to invert it and the process
of inverting it is really the same as
subtracting this value from that minimum
value at the top sometimes it's a little
bit easier to like visualize that but
just so that we can get through the rest
of the example I'm gonna like just let
you guys figure that out or look at
examples again very formulaic once you
figure it out like it's pretty
straightforward if on the other hand if
you ever do bar graphs where the bars go
like horizontally you don't have to do
this you can actually just set like a
solid height for the bars and you don't
have to figure out any of the weird
stuff and then it's the width that's
gonna change and that kind of comes
naturally the more of these you make so
I'm taking care of width and we've taken
care of height the next question d3 is
going to ask is it's going to say okay
tell me the X&Y position where I'm
actually going to start drawing this bar
remember that this Y position is still
going to have to correspond to whatever
the scale has told me right the scale is
going to tell me relative to my axis
where does something with a count of 3
have to start where does something with
a count of 21 have to start and so again
I let my scale handle all of this same
thing goes for the X where I've said
okay the amount to the right that I have
to shift with in my canvas is really
going to depend on every other piece of
data that I already have and so as a
result I again leave this to my scale to
figure out this math would be really
hairy to figure out yourself and so I
cannot extol enough the virtues of the
d3 scales notice here again that what I
have said is actually okay actually this
syntax is a little bit funny you'll
notice that I'm using this artist map
again which seems a little bit weird
because we kind of already have this
artist key the reason I had to do it
this way was the following I said to my
scale that the domain meaning any of the
inputs it was going to get we're
actually going to be artist names and so
as a result for a particular piece of
data rather than hand the scale and
artist ID which would come back
undefined because this domain has no
idea I'm sorry it's wrong
this domain has no idea what a one
corresponds to or what a three
corresponds to but it does know what an
ac/dc corresponds to or a Santana
corresponds to and so as a result as I'm
iterating through all of my data and
count data making these bars when I
actually need to use my X ordinal scale
to figure out the x position of my bars
I need to pass it a name and not just an
ID and so we're back to using this
artist map finally this is the like last
little mildly fancy thing where you said
okay great
I've made this visualization it's pretty
it's it's there but the whole idea
behind d3 is to make things visual and
interactive and to make things
interactive you can actually start
layering some of these JavaScript ideas
for example listeners in this case we're
going to say okay let's actually add a
click listener there are other listeners
like mouse over Mouse off these are
things that I highly recommend googling
but they work in kind of just the
intuitive way that you might expect
buttons to work on with just regular
JavaScript on a regular HTML page or I
said okay if someone ever clicks on a
particular bar please note that for that
particular bar I want you to get
whatever is going to get returned from
this function call I could have written
this entire function in here but for the
sake of clarity and segmenting I made
the decision to actually segment it away
into another function in case for
example my application ever grew and I
wanted to use it on other places on the
page but notice what I've passed is the
artim artist name the artist ID and the
actual album data that I was dealing
with there and in fact this is the
entire data set so to get that artists
name
notice again that I'm using this artist
map just worth noting and basically what
we're going to say is okay every time
someone clicks on this bar go ahead and
run this function up until this point
what we've done
is literally just the following right
we've made axes such that they are
calculated properly for the amount of
data that we're going to do right but in
fact the very first thing we did was
load in this data and clean it in such a
way that it was going to work with what
we wanted to visualize this included
sorting the data this included if this
were more like fancy and real world data
set it might also include iterating
through and taking care of anything like
nan values right where there literally
is no value these are things that you're
going to have to think about as you're
visualizing your data how do you want to
visualize a nan do you want to visualize
it as a zero do you want to just
literally cut it out of your data set
and these are kind of like big
philosophical questions that are worth
asking yourself as you visualize data in
addition to all of that remember that I
actually cut down our data set because I
thought that fewer would be more
interesting because it would be easier
to read and then keep in mind that we
did a lot of math to actually handle
making the axes in addition to then
drawing the axes onto the canvas that
final thing we did is actually dictating
a lot of what is happening over here
remember that JavaScript one of its
primary objectives in life is to change
the DOM and so in fact what's happening
here is that every time I click I am
actually appending new information to a
div that I had already set up over here
if you're curious to see this in the
inspector you can remember that I had
this just empty div with the ID albums
and in fact what that little function
that I'm going to show you in a second
is going to do is it's going to find
that div and append to it an unordered
list and what this is going to end up
doing is showing us more interesting
information about the data that we've
interacted with from the bar graph so to
see what that looks like pretty quickly
here's our just normal query selector
where I've said okay find me this thing
called the artist span for reference
again if we go back to index we'll see
that in fact I wanted some nice way to
put the name of the artist actually
within this header so within this entire
h3 I used a little trick where I said
okay I'm going to include a span which
is really just an empty
space in the HTML into which you can
then put other pieces of HTML in this
case I gave that span an ID but notice
that there's nothing in the span at
least not with you not at the beginning
and again I'll just point your attention
to this empty div with the ID albums if
we go back to mean notice that I said
okay I'm gonna select that span and
within its inner HTML I'm gonna go ahead
and just append that artist name and
that is literally what is dictating
something like Pearl Jam appearing here
or Santana appearing here the unordered
list is a little bit more complicated
but only slightly so where you can
imagine that really what I was doing as
I was making this was I was saying okay
I know I need to start an unordered list
tag and I need to end an unordered list
tag and in fact you'll notice here that
I didn't even close the unordered list
in fact Chrome and HTML were smart
enough to know that if I opened an
unordered list it should probably close
it but to be a little bit more precise
in what we're doing you can go ahead and
actually just close that tag just to
kind of tie up loose ends but you'll
notice that I said okay I'm going to
iterate through each one of the album's
and I'm going to say okay if the album
that I'm holding right now if that
artist ID matches the ID of the thing
that was clicked on I'm going to
consider this a match and as a result
I'm going to say okay this album this
title actually correspond 'add to the
artist that my user clicked on and so
I'm going to append it to this growing
string of HTML which I can then display
later if I consul logged this UL list
for you you would see that it's really
just an ugly string of HTML it has two
UL tags on the outside and a bunch of
allies on the inside or the thing within
the li is really just this album title
notice that I'm using this JavaScript a
string concatenation operator and in
fact I like it a lot
because you can do really fancy things
with it
and finally what I've said is okay I've
iterated through all of the data I have
made this new string let's go ahead and
display it and to do that I select that
div again
using its ID which was albums I go ahead
and say okay it's innerhtml is now going
to equal that ridiculous string that I
just made and you'll notice that if we
then actually inspected this element
what we have done is we've inputted this
entire string here and that is how we
went ahead and made a very simple
visualization are there fancier things
you can do with d3 absolutely you can do
brushing you can do filtering you can
make your visualizations move in cool
ways depending on what your user has
decided to input in terms of parameters
because this is just a quick
demonstration I didn't want to go
through all of that today but again I
highly recommend checking out some of
the examples online and with that I
think I'm going to wrap up if there's
any questions I'm happy to take them
yeah
or something like turning the quarters
into like yeah so that's a great
question so the question here was how
easy would it be to animate the bars or
how easy would it be to make these more
like circles instead of actual bars so
those are kind of two separate questions
in terms of the animation itself what
you can do is there is a there's
actually a d3 I don't know what to call
it I guess it's part of the chain called
transform so you would say like dot
transform and what the transformation
would do is it would actually animate
things for you sometimes the
transformations are a little finicky
because you have to put them in like
exactly the right place and so what I
would recommend doing for that is
looking up examples I could probably
guess it where it's supposed to go in
this but I don't want to do that because
that's gonna be messy on the other hand
how easy is it to make these points
instead of rectangles super easy where
if you think about it a point is really
just a circle so instead of appending
rectangles what instead I could have
done was appended circle so like I
literally would just change this to
circle but unlike rectangles circles
actually now need to have an idea of
where its center point is going to be
and it has to have an idea of what its
radius is going to be and the idea here
is very similar to what you're doing
with the scales where you just need to
configure your scales a little bit
differently to give you that point that
you want but otherwise it's actually
fairly simple and again great examples
online yeah all right well if there's no
other questions I'm going to wrap up I
will gladly send this code thanks so
much for coming and this this was cs50
question mark