Interactive clustering and reorganizing in D3 bubble charts
Interactive clustering and reorganizing in D3 bubble charts
Transcript
so so far we have made this pretty fun
bubble chart it is a collection of
musical artists that are different
bubbles their bubbles are sized
according to the number of albums they
have sold worldwide and each of these
bubbles has a picture of the artist as
the background so this is the CSV we're
working from every artist has a name
every artist has sales that's the size
of the bubble and every artist has an
image path we use that in order to get
their images and every artist has a
decade so we are now going to use the
decade so that when you click a button
all of the pre 2000 artists will go to
the left and all the post 2000 artists
will go to the right so it's going to be
kind of like this New York Times piece
from 2012 where you click types of
spending and they split and you click
all spending and they come back together
so if we're going to do this we're going
to have to do two things the first one
is the easiest and that is expand this
graphic to be a little bit wider so we
have a little bit more room to work with
right now it's 500 by 500 let's make it
500 by 900 width great so the reason why
all of these bubbles are moving and
moving towards the center is because
we're using something in d3 called a
force simulation so this is our force
simulation right here and a force
simulation is a collection of forces and
the combination of all of these forces
is what makes these circles go to a
certain place so we can see right now
we've defined three different forces X Y
and collide you can make up whatever
kind of names you want for these it's
just if you revised the force later you
end up needing to use the exact same
name for them so let's go one by one
through these forces and we'll start
from the bottom and work our way up
so the first force is called collide and
it is a d3 force collide d3 force
collide is all about not
your circles overlap one another if we
said so normally when you have a force
you just give it a number and it says
okay I'm going to apply the same force
to every single circle but the way the
d3 force collide works is you need to
make the colliding force of your circle
the anti colliding force of your circle
on the same as the radius of your circle
so if we go down a little that our
circle our circle is scaled according to
the number of sales that the artist has
made so for example Fetty WAP right here
has sold 1 million albums worldwide so
his circle is only a 10 radius whereas
Madonna here has sold 300 million albums
worldwide
so her circle is I believe it 80 radius
so if we go back up here we will see
that we're using the exact same thing
with the force collide function every
time it says how anti collide er what
kind of a force field should I put up
around this node they say oh well it
depends on how many sales this artist
has had so if Fetty WAP gets a very
small one here let's let's just replace
this let's say we made every one 20 so
now everyone is clustered around each
other let's say we made every 180 so we
get a lot more space going on out there
it's a nice nice equal spacing there but
not what we want so because we want this
to be different for every single
different circle we're going to make it
a function because that's what you do
and you say return radius scale D sales
and we add a little bit of extra spacing
just because I think it looks nice but I
did this wrong oh yes we need another
another parenthesis there alright so
looking good so now we want to do is we
want to add two buttons to the page and
we're just going to make this easy
going to edit HTML and we're just going
to add a button and it's going to say
decade split and another button and
we're going to call that combine we need
to give them IDs so we can talk about
them later but that's pretty much as
simple as it gets their buttons and we
need to listen for events on them so
we're going to listen for clicks on both
the decade button and the combine button
so let's get going we are going to say
III select decade on click function no D
there console.log you clicked me so
every time we click the decade button
it's going to run this let's test that
and now we'll go talk about our other
forces okay so we have two other forces
here we have a Y force and we have an X
force and the Y force is a force in the
on the y axis and this is the target Y
so the target Y is height divided by 2
so height divided by 2 is this line
going across the middle this invisible
line on this is 0 over the top height is
at the bottom height divided by 2 is in
the middle so this force is like it's
like gravity acting to pull everything
towards the middle of the page if let's
say we got rid of force X you would see
that everything clusters along the y
axis and has no regard for the x axis
and it would be the same it's the same
thing with the X we use a force called
force X we're saying with divided by 2
this is zero this is with
right hand side with / - is right in the
middle so we have one force that's
trying to push things towards the middle
along the x-axis and one force that's
trying to push things to the middle on
the y-axis and what that generally does
is just pushes everything towards the
center each one of these functions each
one of these forces has a strength so
they're not very strong forces but
they're enough to get everything to
being metal alright so what we are want
to do is instead of pushing everything
towards the middle we want to have some
things on the left hand side and some
things on the right hand side now we're
going to go back to when we had the
colliding force here what the colliding
force did was it changed based on our
data point right so based on the sales
of the data point on it either if it
changed the size of the radius scale and
so what we need to do now is what's the
difference between on the left hand side
in the right hand side the x-axis so
what we need to do is make it so our
force X changes based on our data points
so some of them will go over here and
some of them will go over there so first
we're going to do without clicking the
button and then we'll move it down to
being where we click the button so right
now
width divided by 2 is where the X force
is always trying to push everything it's
always trying to push everything right
along this line right in the middle but
if we want it to happen on a per element
basis on a per data point basis you just
make a function right so return let's
just always make it still width divided
by 2 or fresh fine so this is actually
getting a little bit complicated so I'm
going to pull it out as a variable so
force X equals
and I'm going to do the same thing with
force collide so var force collide
equals this so instead of typing it all
inside this tiny area here we are able
to map them alright everything still
works well so every time we change this
force X here it's still going to be
changing on the fourth part of the
simulation so right now it is still
saying we want everything to be with
divided by 2 on the x-axis what we want
to do is say sometimes over here
sometimes on sometimes on the left-hand
side sometimes on the right-hand side
now if we look at our excel decade is
the column we're looking at and it is
pre 2000 or post 2000 so we could do
something as simple as this if d decade
is equal to pre 2000 return let's say a
150 otherwise return how why is this 900
return 800 so let's just make this 200
and 800 so if you are before 2000 your
ex force is going to push you towards
200 otherwise it's going to force you
push you towards 800 so we'll save this
and will refresh and there you go I
think these might be a little close to
the page if we added more information on
there so let's push them in a little bit
further maybe 250 and 750 yeah that
looks pretty good so now we have a 1x
force for people over here in the pre
2000s
and then one X force or the export is
giving out a different value for people
pre and post 2000 but here's the thing
we need this to change based on wind we
push those buttons
so let's actually let's start the
combine button first I know we already
made the decade split button a little
bit but let's work on the combine button
now so if we go down here
d3 dot select and I believe I hold this
button combined yes the idea is combine
combine on click function console dot
log combine the bubbles and yes it is
now saying combine the bubbles so what
we want to do when someone clicks
combine the bubbles is apply a new force
X so right now the force X were using is
splitting everything apart but we want
to pull everything together so there
there are a few ways to do this um we'll
do with the inelegant wave first and
we'll make it a more elegant way later
so right here see that the simulation is
called simulation and we named the X
force X so all we need to do actually is
go down here and we're going to say when
we click combined simulation dot Force X
and then we can actually overwrite that
force with a new one
so d3 for sex where do we want it to go
everything with / - how strong do we
want to make it strength is optional but
let's just use the strength that we have
up here 0.05 0.05 so what this is going
to do is the simulation it's going to
grab the simulation
it's going to take that X force of the
force on the x-axis which was pushing
them into two separate groups and it's
going to replace it with one force that
acts equally on every one pushing them
towards the middle so the two exporters
aren't going to have to fight with one
another because we're saying force X
that's going to overwrite our old one so
save it refresh and then push the button
what happens oh it moves a little bit
but it doesn't seem to quite get back
together so one thing we might think
about doing is changing the strength
let's make it a little bit stronger
because who knows what's going on there
right point five instead of point zero
five combined yeah it works but then
it's overpowering the y-axis one so the
problem we're having is let's let these
settle and then click combined they
don't really move at all
but if I very quickly hit refresh and
then combine they combine successfully
so what's happening here is all of the
nodes of slowing down and they're losing
energy and they're deciding oh I'm
basically too sleepy on to start running
again so what we're going to need to do
is two lines of code alpha target zero
point five restart every time you change
the simulation you are going to give it
a little bit of a nudge with an alpha
target to tell it how quickly it should
be moving and then you're going to say
restart the simulation from the
beginning with our new force so they
come apart previously when we clicked
combine everything was too sleepy but
this time it's working because we're
saying hey get started again start start
this over again and now we can do the
same thing with a decade split where we
just cut and paste this code and instead
of this force X
oh hey remember up at the top we
actually saved this we have this force X
already here we already have this
variable what if we just use that again
so every time we want to split we can
just use that variable so we'll save
will refresh combine split combined
split now it's kind of ugly to have all
of these forces written in different
places some of the forces are written
here on this one we're just using a
variable but it's really written up top
so we're going to do is we're going to
rename all of our forces and we're just
going to write them once so this force X
I'm going to call force X combined then
I'm going to make another one and I'm
just going to call it very sorry force X
separate and then force X combined so
now I'm just defining them all in the
same spot so if we want to start our
simulation off in one spot we say our X
force should be Force X combined we can
go down here and say our X force should
be Force X combined whereas if we click
the decade button it should be Force X
separate it just makes things a little
bit more readable just a little bit more
readable so I'm going to refresh they
will all start off together and we can
split them we can combine them split and
combine them what you're going to find
is it's going to be it's kind of tough
to figure out how to get the right
values for things like alpha targeting
for things like strength because you'll
see these are kind of still playing
around and there's still a lot of
overlap so you might think oh I should
make my forces a little bit stronger um
maybe 0.1 0.1 but in the end yeah so
that that didn't really work on the
combining because it needs to be the
same strength as your Y force otherwise
it will cluster either on the x axis or
the y axis and you'll see the adam
levine here and drake there or jittering
a lot so let's undo we'll go back to
0.05 this ends up being an alpha target
issue so if you made the alpha target
may be 0.25 it will move a little bit
more slowly and you say well what are
the magic numbers what should i really
make be my alpha target and all of my
strengths and the answer is I don't know
I don't know it ends up just being a
magic game of changing all of these
numbers until something makes sense so
in order to get your visual to be what
you'd like if it's interactive change
your alpha targets and if it's not
interactive if it's just a or if the
arrangement is an interactive just keep
looking at all of your strengths all of
your strengths just to see how well
they're doing on play around with the
numbers just do it until it looks right
kind of the unfortunate part with force
diagrams okay so what do we do we
learned that using the power of buttons
you can take the forces name right here
and then you can overwrite it in a
function so we were using this force X
combine as X and then later we said no
no we're going to replace this force
with a new force that's going to keep
things separate but every time you
change forces you should probably give
it an alpha target and then give it a
restart and then that will make your
simulation kind of perk up again and
rearrange itself in the way that it
should
bubble chart it is a collection of
musical artists that are different
bubbles their bubbles are sized
according to the number of albums they
have sold worldwide and each of these
bubbles has a picture of the artist as
the background so this is the CSV we're
working from every artist has a name
every artist has sales that's the size
of the bubble and every artist has an
image path we use that in order to get
their images and every artist has a
decade so we are now going to use the
decade so that when you click a button
all of the pre 2000 artists will go to
the left and all the post 2000 artists
will go to the right so it's going to be
kind of like this New York Times piece
from 2012 where you click types of
spending and they split and you click
all spending and they come back together
so if we're going to do this we're going
to have to do two things the first one
is the easiest and that is expand this
graphic to be a little bit wider so we
have a little bit more room to work with
right now it's 500 by 500 let's make it
500 by 900 width great so the reason why
all of these bubbles are moving and
moving towards the center is because
we're using something in d3 called a
force simulation so this is our force
simulation right here and a force
simulation is a collection of forces and
the combination of all of these forces
is what makes these circles go to a
certain place so we can see right now
we've defined three different forces X Y
and collide you can make up whatever
kind of names you want for these it's
just if you revised the force later you
end up needing to use the exact same
name for them so let's go one by one
through these forces and we'll start
from the bottom and work our way up
so the first force is called collide and
it is a d3 force collide d3 force
collide is all about not
your circles overlap one another if we
said so normally when you have a force
you just give it a number and it says
okay I'm going to apply the same force
to every single circle but the way the
d3 force collide works is you need to
make the colliding force of your circle
the anti colliding force of your circle
on the same as the radius of your circle
so if we go down a little that our
circle our circle is scaled according to
the number of sales that the artist has
made so for example Fetty WAP right here
has sold 1 million albums worldwide so
his circle is only a 10 radius whereas
Madonna here has sold 300 million albums
worldwide
so her circle is I believe it 80 radius
so if we go back up here we will see
that we're using the exact same thing
with the force collide function every
time it says how anti collide er what
kind of a force field should I put up
around this node they say oh well it
depends on how many sales this artist
has had so if Fetty WAP gets a very
small one here let's let's just replace
this let's say we made every one 20 so
now everyone is clustered around each
other let's say we made every 180 so we
get a lot more space going on out there
it's a nice nice equal spacing there but
not what we want so because we want this
to be different for every single
different circle we're going to make it
a function because that's what you do
and you say return radius scale D sales
and we add a little bit of extra spacing
just because I think it looks nice but I
did this wrong oh yes we need another
another parenthesis there alright so
looking good so now we want to do is we
want to add two buttons to the page and
we're just going to make this easy
going to edit HTML and we're just going
to add a button and it's going to say
decade split and another button and
we're going to call that combine we need
to give them IDs so we can talk about
them later but that's pretty much as
simple as it gets their buttons and we
need to listen for events on them so
we're going to listen for clicks on both
the decade button and the combine button
so let's get going we are going to say
III select decade on click function no D
there console.log you clicked me so
every time we click the decade button
it's going to run this let's test that
and now we'll go talk about our other
forces okay so we have two other forces
here we have a Y force and we have an X
force and the Y force is a force in the
on the y axis and this is the target Y
so the target Y is height divided by 2
so height divided by 2 is this line
going across the middle this invisible
line on this is 0 over the top height is
at the bottom height divided by 2 is in
the middle so this force is like it's
like gravity acting to pull everything
towards the middle of the page if let's
say we got rid of force X you would see
that everything clusters along the y
axis and has no regard for the x axis
and it would be the same it's the same
thing with the X we use a force called
force X we're saying with divided by 2
this is zero this is with
right hand side with / - is right in the
middle so we have one force that's
trying to push things towards the middle
along the x-axis and one force that's
trying to push things to the middle on
the y-axis and what that generally does
is just pushes everything towards the
center each one of these functions each
one of these forces has a strength so
they're not very strong forces but
they're enough to get everything to
being metal alright so what we are want
to do is instead of pushing everything
towards the middle we want to have some
things on the left hand side and some
things on the right hand side now we're
going to go back to when we had the
colliding force here what the colliding
force did was it changed based on our
data point right so based on the sales
of the data point on it either if it
changed the size of the radius scale and
so what we need to do now is what's the
difference between on the left hand side
in the right hand side the x-axis so
what we need to do is make it so our
force X changes based on our data points
so some of them will go over here and
some of them will go over there so first
we're going to do without clicking the
button and then we'll move it down to
being where we click the button so right
now
width divided by 2 is where the X force
is always trying to push everything it's
always trying to push everything right
along this line right in the middle but
if we want it to happen on a per element
basis on a per data point basis you just
make a function right so return let's
just always make it still width divided
by 2 or fresh fine so this is actually
getting a little bit complicated so I'm
going to pull it out as a variable so
force X equals
and I'm going to do the same thing with
force collide so var force collide
equals this so instead of typing it all
inside this tiny area here we are able
to map them alright everything still
works well so every time we change this
force X here it's still going to be
changing on the fourth part of the
simulation so right now it is still
saying we want everything to be with
divided by 2 on the x-axis what we want
to do is say sometimes over here
sometimes on sometimes on the left-hand
side sometimes on the right-hand side
now if we look at our excel decade is
the column we're looking at and it is
pre 2000 or post 2000 so we could do
something as simple as this if d decade
is equal to pre 2000 return let's say a
150 otherwise return how why is this 900
return 800 so let's just make this 200
and 800 so if you are before 2000 your
ex force is going to push you towards
200 otherwise it's going to force you
push you towards 800 so we'll save this
and will refresh and there you go I
think these might be a little close to
the page if we added more information on
there so let's push them in a little bit
further maybe 250 and 750 yeah that
looks pretty good so now we have a 1x
force for people over here in the pre
2000s
and then one X force or the export is
giving out a different value for people
pre and post 2000 but here's the thing
we need this to change based on wind we
push those buttons
so let's actually let's start the
combine button first I know we already
made the decade split button a little
bit but let's work on the combine button
now so if we go down here
d3 dot select and I believe I hold this
button combined yes the idea is combine
combine on click function console dot
log combine the bubbles and yes it is
now saying combine the bubbles so what
we want to do when someone clicks
combine the bubbles is apply a new force
X so right now the force X were using is
splitting everything apart but we want
to pull everything together so there
there are a few ways to do this um we'll
do with the inelegant wave first and
we'll make it a more elegant way later
so right here see that the simulation is
called simulation and we named the X
force X so all we need to do actually is
go down here and we're going to say when
we click combined simulation dot Force X
and then we can actually overwrite that
force with a new one
so d3 for sex where do we want it to go
everything with / - how strong do we
want to make it strength is optional but
let's just use the strength that we have
up here 0.05 0.05 so what this is going
to do is the simulation it's going to
grab the simulation
it's going to take that X force of the
force on the x-axis which was pushing
them into two separate groups and it's
going to replace it with one force that
acts equally on every one pushing them
towards the middle so the two exporters
aren't going to have to fight with one
another because we're saying force X
that's going to overwrite our old one so
save it refresh and then push the button
what happens oh it moves a little bit
but it doesn't seem to quite get back
together so one thing we might think
about doing is changing the strength
let's make it a little bit stronger
because who knows what's going on there
right point five instead of point zero
five combined yeah it works but then
it's overpowering the y-axis one so the
problem we're having is let's let these
settle and then click combined they
don't really move at all
but if I very quickly hit refresh and
then combine they combine successfully
so what's happening here is all of the
nodes of slowing down and they're losing
energy and they're deciding oh I'm
basically too sleepy on to start running
again so what we're going to need to do
is two lines of code alpha target zero
point five restart every time you change
the simulation you are going to give it
a little bit of a nudge with an alpha
target to tell it how quickly it should
be moving and then you're going to say
restart the simulation from the
beginning with our new force so they
come apart previously when we clicked
combine everything was too sleepy but
this time it's working because we're
saying hey get started again start start
this over again and now we can do the
same thing with a decade split where we
just cut and paste this code and instead
of this force X
oh hey remember up at the top we
actually saved this we have this force X
already here we already have this
variable what if we just use that again
so every time we want to split we can
just use that variable so we'll save
will refresh combine split combined
split now it's kind of ugly to have all
of these forces written in different
places some of the forces are written
here on this one we're just using a
variable but it's really written up top
so we're going to do is we're going to
rename all of our forces and we're just
going to write them once so this force X
I'm going to call force X combined then
I'm going to make another one and I'm
just going to call it very sorry force X
separate and then force X combined so
now I'm just defining them all in the
same spot so if we want to start our
simulation off in one spot we say our X
force should be Force X combined we can
go down here and say our X force should
be Force X combined whereas if we click
the decade button it should be Force X
separate it just makes things a little
bit more readable just a little bit more
readable so I'm going to refresh they
will all start off together and we can
split them we can combine them split and
combine them what you're going to find
is it's going to be it's kind of tough
to figure out how to get the right
values for things like alpha targeting
for things like strength because you'll
see these are kind of still playing
around and there's still a lot of
overlap so you might think oh I should
make my forces a little bit stronger um
maybe 0.1 0.1 but in the end yeah so
that that didn't really work on the
combining because it needs to be the
same strength as your Y force otherwise
it will cluster either on the x axis or
the y axis and you'll see the adam
levine here and drake there or jittering
a lot so let's undo we'll go back to
0.05 this ends up being an alpha target
issue so if you made the alpha target
may be 0.25 it will move a little bit
more slowly and you say well what are
the magic numbers what should i really
make be my alpha target and all of my
strengths and the answer is I don't know
I don't know it ends up just being a
magic game of changing all of these
numbers until something makes sense so
in order to get your visual to be what
you'd like if it's interactive change
your alpha targets and if it's not
interactive if it's just a or if the
arrangement is an interactive just keep
looking at all of your strengths all of
your strengths just to see how well
they're doing on play around with the
numbers just do it until it looks right
kind of the unfortunate part with force
diagrams okay so what do we do we
learned that using the power of buttons
you can take the forces name right here
and then you can overwrite it in a
function so we were using this force X
combine as X and then later we said no
no we're going to replace this force
with a new force that's going to keep
things separate but every time you
change forces you should probably give
it an alpha target and then give it a
restart and then that will make your
simulation kind of perk up again and
rearrange itself in the way that it
should