I am trying to replicate the following plot in dyGraph
or highcharter
.
df %>%
ggplot(aes(x = mts2, y = price)) +
geom_point() +
geom_jitter() +
facet_wrap(~ type, scales = "free_y", ncol = 1) +
stat_smooth(method = "lm", formula = y ~ x + I(x^2), size = 1, color = "red")
However, I would like it interactive so when the user hovers over one of the points a line is drawn to connect the rental
and the purchases
. So when I hover over the regression line it will highlight the regression in the other plot.
I am trying to recreate the same plot but in dygraphs
or highcharter
where I can highlight the same points in both regressions. (i.e. when we hoverover 80
mts2 and the points around 400,000
price it should highlight the points in the top graph around 1,500
Code:
library(dygraphs)
df %>%
filter(type == "comprar") %>%
select(-c(type, habs)) %>%
dygraph(main = "myTitle") %>%
dyOptions(drawPoints = TRUE) %>%
dySeries(drawPoints = TRUE, color = "#0099F9")
library(highcharter)
df %>%
highchart() %>%
hc_title(text = "Scatter chart with size and color") %>%
hc_add_series(df, "scatter", hcaes(x = price, y = mts2, size = mts2, color = mts2))
Data:
df = structure(list(price = c(1600, 1200, 249000, 288000, 775000,
350000, 715000, 330000, 375000, 925, 1250, 300000, 425000, 489000,
1200, 550000, 1895, 310000, 289000, 450000, 1250, 288000, 1000,
600, 1100, 350000, 1200, 339000, 405000, 427000, 299000, 218000,
159900, 360000, 365000, 725, 405000, 300000, 715000, 1300, 1400,
1500, 415000, 1500, 663, 350000, 365000, 230000, 515000, 259000,
310000, 405000, 288000, 350000, 288000, 1300, 350000, 1350, 715000,
350000, 715000, 185000, 2200, 288000, 353800, 290000, 229000,
365000, 1900, 1300, 590000, 180000, 1050, 1900, 1100, 1950, 288000,
1995, 112000, 369000, 593000, 550000, 365000, 715000, 1800, 713000,
1100, 260000, 375000, 715000, 338000, 288000, 1900, 288000, 2800,
2450, 1990, 260000, 415000, 745000), habs = c(1, 1, 1, 4, 3,
4, NA, 4, 2, 2, 2, 2, 4, 3, 3, 4, 2, 2, 3, 4, 1, 4, 1, 1, 2,
5, 3, 4, 3, 4, 2, 2, NA, 4, 3, 1, 3, 3, 3, 3, 3, 2, 4, 2, 1,
3, 3, 3, 2, 1, 2, 3, 4, 4, 4, 3, 4, 3, NA, 3, 3, 1, 3, 4, 1,
4, 3, 3, 1, 2, 3, 2, 1, 1, 2, 2, 4, 2, 1, 3, 2, 4, 3, 3, 2, 3,
3, NA, 2, 3, 3, 4, 1, 4, 4, 4, 1, NA, 4, 3), mts2 = c(70, 65,
55, 76, 121, 87, 109, 85, 81, 46, 65, 55, 100, 102, 65, 122,
66, 51, 85, 99, 50, 75, 55, 10, 75, 87, 71, 75, 83, 118, 85,
57, 45, 112, 63, 40, 83, 75, 109, 91, 74, 58, 100, 75, 42, 82,
90, 65, 104, 52, 55, 83, 79, 87, 76, 77, 87, 88, 109, 83, 109,
46, 145, 76, 40, 66, 63, 90, 45, 65, 115, 44, 46, 45, 73, 90,
79, 110, 42, 81, 73, 115, 94, 109, 70, 104, 75, 58, 80, 109,
92, 79, 45, 76, 122, 160, 47, 58, 100, 104), type = c("alquiler",
"alquiler", "comprar", "comprar", "comprar", "comprar", "comprar",
"comprar", "comprar", "alquiler", "alquiler", "comprar", "comprar",
"comprar", "alquiler", "comprar", "alquiler", "comprar", "comprar",
"comprar", "alquiler", "comprar", "alquiler", "alquiler", "alquiler",
"comprar", "alquiler", "comprar", "comprar", "comprar", "comprar",
"comprar", "comprar", "comprar", "comprar", "alquiler", "comprar",
"comprar", "comprar", "alquiler", "alquiler", "alquiler", "comprar",
"alquiler", "alquiler", "comprar", "comprar", "comprar", "comprar",
"comprar", "comprar", "comprar", "comprar", "comprar", "comprar",
"alquiler", "comprar", "alquiler", "comprar", "comprar", "comprar",
"comprar", "alquiler", "comprar", "comprar", "comprar", "comprar",
"comprar", "alquiler", "alquiler", "comprar", "comprar", "alquiler",
"alquiler", "alquiler", "alquiler", "comprar", "alquiler", "comprar",
"comprar", "comprar", "comprar", "comprar", "comprar", "alquiler",
"comprar", "alquiler", "comprar", "comprar", "comprar", "comprar",
"comprar", "alquiler", "comprar", "alquiler", "alquiler", "alquiler",
"comprar", "comprar", "comprar")), row.names = c(NA, -100L), class = c("tbl_df",
"tbl", "data.frame"))
I'm going to a wild stab at what I think you're looking for here. There's a lot you can do with these libraries. I don't know what you wanted to see in the tooltips over the regressions, either.
For this solution, I opted to go with highcharter
.
First, I used imap
to create the two plots. I've added many comments so you can see the purpose of the calls. If anything is unclear, let me know.
library(highcharter)
library(tidyverse)
library(htmltools)
imap(unique(df$type), function(j, k) { # index & type in df
plt <- df %>% filter(type == j) %>% # filter for the type
hchart("point", regression = T, # add poly reg line
regressionSettings = list(color = "red", type = "polynomial",
hideInLegend = T), # no legend
hcaes(x = mts2, y = price)) %>%
hc_add_dependency("plugins/highcharts-regression.js") %>% # tie-in reg dep
hc_xAxis(min = 5, max = 160, crosshair = T) %>% # all w/ same x rng
hc_tooltip(useHTML = T, crosshair = T)
assign(paste0("plt", k), plt, envir = .GlobalEnv) # add plot to env
})
Now, to render both plots together with synched tooltips, I've used browsable
. If you're using RStudio or another IDE with a viewer pane, you'll need to send the results to the browser to see the plots combined. In Rstudio, you can just click on the icon to send it there. The icon looks like this... (center-ish in the viewer pane).
The remaining code is almost entirely Javascript/JQuery. Again, I've added a lot of comments here to explain what's happening.
I wanted to point out one particular line:
point = chart.series[1].searchPoint(event, true); /* get closest point; reg line only */
In this declaration of the point
object, the [1]
after series
is what's telling this entire chunk of code to only align the regressions between the plots. For example, if you changed this to [0]
it would ignore the regression lines and focus on the points in both plots.
browsable(tagList(
tags$script(HTML("
setTimeout(function() { /* using id from div */
$('#hc_container').bind('mousemove touchmove touchstart', function(e) {
var chart, point, i, event;
for (i = 0; i < Highcharts.charts.length; i++) { /* loop through both charts */
chart = Highcharts.charts[i]; /* identify the chart */
event = chart.pointer.normalize(e.originalEvent); /* find chart coordinates */
point = chart.series[1].searchPoint(event, true); /* get closest point; reg line only */
if (point) { /* if point found, tip it */
point.highlight(e);
}
}
});
}, 500);
Highcharts.Point.prototype.highlight = function(event) { /* executes tooltip from trigger */
event = this.series.chart.pointer.normalize(event); /* capture that event occurred */
this.onMouseOver(); /* show marker */
this.series.chart.tooltip.refresh(this); /* show tooltip */
this.series.chart.xAxis[0].drawCrosshair(event, this); /* show crosshair */
};
Highcharts.Pointer.prototype.reset = function() { /* vigilant tooltip */
return null;
};
")),
div(id = "hc_container", # this id is used in the JQuery/Javascript above
div(plt1, style = 'height:50%; width: 100%;'), # first plot
div(plt2, style = 'height:50%; width: 100%;'), # second plot
style = "height:100%; width:100%;"))) # container styles
For customizing things like the tooltip in the regression line (or any other settings for the regression line), use this site. For some reason, when I go to this site randomly the readme
doesn't load. If I refresh my browser it shows up immediately. I'm not sure what's up with that, but in case it's blank for you, that's all you've got to do.
If you have any questions, let me know.