Unfortunately, compared to
ggplot2, D3’s learning curve feels quite steep and I am not yet able to work with it yet.
Fortunately, there are other interactive graphing libraries out there that I can use to get a first feel for creating interactive plots.
Therefore, I decided to play around with this R package in the hope of figuring out how it works. Also, I summarized what I played around with in this blog post by writing what I like to call an “exploratory introduction”.
As the name implies, this is not really a formal introduction to
plotly and more of an experience report.
Nevertheless, I suspect that this can be useful for people who have already knowledge about
ggplot2 and want to get started with
plotly as well.
Further, in case you do not want to read my informal commentary, you can also check out the video version of this blog post. Think of it as a summary of this blog post.
As of now, I plan on doing a similar exploratory introduction to
r2d3 which is an R interface to D3.
Possibly, this will then be combined with knowledge I gathered from Scott Murray’s book.
One Side Note before We Dive in
To work around this issue, I had to save the plots in an auxillary html-file and include it as a separate frame. This is why you will find that, here, all plots are saved in a variable (for later export) even if it does not really make sense to save it for plotting purposes.
Finally, be aware that, for some reason, interactive
plotly plots are quite large such that it might take some time to load them all.
From ggplot2 to plotly
Let us begin by transforming a ggplot to a plotly plot.
Using a built-in function from the
plotly package, it is straight-forward to convert a ggplot.
Marvel at what one can do here:
- Get additional information by hovering your cursor over a point
- Filter classes by clicking on the corresponding legend items
- Click and draw a rectangle with your cursor to zoom into the plot
But there is one thing that bothers me. If I move the cursor across the plot window, then the plotly options bar at the top of the window overlaps the “class” legend label. Can I fix this by moving the legend to the bottom?
Hmm, it appears that the legend cannot be moved by this.
Do other changes in
theme() get registered?
Let’s check by applying a theme.
Apparently, at least some changes will be conducted.
Let’s see, if I can use
layout() as shown in the getting started documentation of plotly to move the legend.
The R documentation of the
layout() function is somewhat minimalistic.
Basically, it refers to the online plotly reference manual.
Using the table of content on that website, one can easily find the layout options.
I believe the options
yanchor are exactly what I need as both of them can be set to options like
Though, I wonder why the value
auto was not changed by
ggplotly() as the initial plot
legend.position = "bottom".
In any case, I am not a hundred percent sure what kind of syntax
An example in the R documentaion would have been nice.
Well, let’s try the straight-forward approach then.
Well, that didn’t go as expected, but the warning displays valid attributes and
legend is among them.
Upon closer inspection, I also realize that, according to the reference manual,
yanchor have parent
So, I guess, I will have to use this somehow.
Maybe, pass a list to
At least this did not crash again but the resulting plot does not look as I would expect it to.
Let’s see what happens when we change
yanchor as well and then we’ll go from there.
Unsurprisingly, this did not help at all.
In retrospect, I don’t know how I could think that changing
yanchor as well would magically cure things.
Again, referring back to the manual (I should really read the descriptions instead of relying on the possible values), it appears that
xanchor only sets a reference points for the option
Same thing for
So, how about changing
Possible values for both options range from -2 to 3, so my best guess is that ranges from 0 to 1 refer to the window the points are plotted in.
Consequently, moving the legend to the bottom could be as easy as using a positive
x value and negative
y value which are both close to zero.
Now, this brings us closer to what I had in mind when I set
legend.position = "bottom" in
Possibly, we can change the orientation of the legend from vertical to horizontal, tweak the
y values a bit and then we’re there.
Scrolling through the manual (again), reveals that there is an option
orientation which can be set to
This sounds promising.
Finally, I am satisfied.
Out of curiosity, let us investigate what had happened, if we had set orientation to
"h" from the start.
This already looks nice enough, so our manual tweaking was not technically necessary.
But then again, this does not recreate what
legend.position = "bottom" usually does.
Now that we understand how
layout() works, we can roam the reference manual and try to tweak the legend box.
Let’s try to change a couple of things.
This does not have to be pretty, we only want to see how plotly works.
Note how we have used lists in lists (in lists) to customize the legend.
Interestingly, our initial blunder of ignoring the “parent” resp. the hierarchy of options earlier helped to understand that as an option’s parent’s name gets longer, e.g.
layout.legend.title.font, we will have to use more convoluted lists to change that option.
Creating a Plotly Chart Manually
Since we have learned how to tweak a plotly object, we might as well figure out how to create one without having to use
It is not that I want to avoid using ggplot altogether but, in principle, it cannot hurt if we can understand plotly’s implementation in the R package
So, from the book Interactive web-based data visualization with R, plotly, and shiny I gather that the
plotly.js library via a Grammar of Graphics approach.
Thus, it works similar to
ggplot2 in the sense that we can add layers of graphical objects to create a plot.
plotly’s case, we pass a plotly object from one
add_* layer to the next (via
These are used to ensure that the variables are mapped from the data (similar to
Alternatively, one could also use
x = mpg$hwy to create the same plot.
Because we can see a lot of overplotting, let us jitter the points. Unfortunately, I couldn’t find a built-in option for that. Therefore, let’s do the jittering manually.
Regarding the customization of the points aka markers, we can pass a list of options (taken from the reference manual again) to the
marker argument in
Alternatively, and what I find surprisingly convenient, we can leave our initial plotly object as it is and pass it to the
This functions works just like the
layout() function we have seen before.
Similarly, we could pass this along to
layout() if we want to customize the legend box again.
For some obscure reason the exact same legend command behaves differently now.
Honestly, I have no clue what is going on here.
If I had to hazard a guess, I would say that during the conversion of a ggplot object to a plotly object via
ggplotly() some default values were implemented that cause the change but this is just a hunch.
Possibly, this is connected to
In any case, we got a glimpse of how the
plotly.js to create interactive plots.
Also, we have learned how to convert a ggplot2 object to a plotly object and how we can customize this further.
Interestingly, when converting from ggplot2 to plotly, the pop-up window that appears when you hover over a point is already customized compared to the default from
Did you notice the difference already?
So, in order to end our “exploratory introduction” let us adjust the
hovertemplate according to the description in the reference manual.
Here, we will use
\n for line breaks.
Notice how the class labels appear outside of the box.
The reference manual refers to this position as “secondary” box.
To get rid of this, we simply add
<extra></extra> to our hover template.
Unfortunately, it appears as if what is not displayed in the primary box cannot be used as part of the hover template.
Thus, we cannot use
Instead, we simply map
class to the
text attribute of the markers as well.
Then, we can use
All right! That’s enough exciting plotting action for today. Hope you enjoyed this blog post and see you next time.