How to Make Scatterplot Points Open a Hyperlink Using Ggplotly - R

How to make scatterplot points open a hyperlink using ggplotly - R

Looks like add_markers(pp, customdata = ~url) has no effect. That works by doing:

p <- ggplot(data = mtcars, aes(x = wt, y = mpg)) + geom_point()
pp <- ggplotly(p)
pp$x$data[[1]]$customdata <- mtcars$url
#pp <- add_markers(pp, customdata = ~url)
ppp <- onRender(pp, "
function(el, x) {
el.on('plotly_click', function(d) {
var url = d.points[0].customdata;
//url
window.open(url);
});
}
")

How to make tiles open a hyperlink using ggplotly - R

It seems the structure was changed a little.

Please check the following:

library(plotly)

mtcars$url <- paste0("https://google.com/search?q=", gsub(" ", "+", rownames(mtcars)))

p <- ggplot(data = mtcars, aes(x = wt, y = mpg, fill = as.character(carb), customdata = url)) +
geom_tile(width = .2, height = 1)
pp <- ggplotly(p)

plotly_json(pp)

ppp <- htmlwidgets::onRender(pp, "
function(el, x) {
el.on('plotly_click', function(d) {
// console.log(d);
var url = d.points[0].data.customdata[0];
window.open(url);
});
}
")
ppp

Adding hyperlinks to Shiny plots

Shiny apps use plotly's postMessage API or plotly.js, both of which expose click, hover, and zoom events. These events aren't yet exposed as callbacks to the underlying shiny server, but they are accessible with custom javascript that you can serve yourself in shiny.

Here's an example with click events:

Adding click events to graphs in Shiny

ui.R

library(shiny)
library(plotly)

shinyUI(fluidPage(
mainPanel(
plotlyOutput("trendPlot"),
tags$head(tags$script(src="clickhandler.js"))
)
))

server.R

library(shiny)
library(plotly)

x = c(1, 2, 3)
y = c(4, 2, 4)
links = c("https://plot.ly/r/",
"https://plot.ly/r/shiny-tutorial",
"https://plot.ly/r/click-events")

df = data.frame(x, y, links)

shinyServer(function(input, output) {

output$trendPlot <- renderPlotly({
# Create a ggplot
g = ggplot(data=df, aes(x = x, y = y)) + geom_point()
# Serialize as Plotly's graph universal format
p = plotly_build(g)
# Add a new key, links, that JS will access on click events
p$data[[1]]$links = links
p

# Alternatively, use Plotly's native syntax. More here: https://plot.ly/r
# plot_ly(df, x=x,y=y,links=links)
})
})

www/clickhandler.js

$(document).ready(function(){
// boiler plate postMessage plotly code (https://github.com/plotly/postMessage-API)
var plot = document.getElementById('trendPlot').contentWindow;

pinger = setInterval(function(){
plot.postMessage({task: 'ping'}, 'https://plot.ly')
}, 100);

var clickResponse = function(e) {
plot = document.getElementById('trendPlot').contentWindow;
var message = e.data;
console.log( 'New message from chart', message );
if(message.pong) {
// tell the embedded plot that you want to listen to click events
clearInterval(pinger);
plot.postMessage({
task: 'listen', events: ['click']}, 'https://plot.ly');
plot.postMessage({
task: 'relayout',
'update': {hovermode: 'closest'},
},
'https://plot.ly');
}
else if(message.type === 'click') {
var curveNumber = message['points'][0]['curveNumber'],
pointNumber = message['points'][0]['pointNumber'];

var link;
var traces = message.points[0].data;
if(traces !== null && typeof traces === 'object') {
link = traces.links[pointNumber];
} else {
link = traces[curveNumber].links[pointNumber];
}

console.log(link);

var win = window.open(link, '_blank');
win.focus();
}
};

window.addEventListener("message", clickResponse, false);

});

Here are some more resources that might be helpful:

  • Adding custom interactivity to plotly charts in javascript with R
  • In particular Binding to click events in JavaScript
  • Getting started with Shiny and plotly
  • Plotly postMessage API for adding custom interactivity to hosted plotly graphs

Using ggplot to link points of interest in scatterplot

The idea is to use geom_line and to define groups (gr) for every segment:

dat <- data.frame(xvar = xvar, yvar = yvar)    
dat2 <- cbind(dat[c(start, end), ], gr = 1:length(start))

ggplot(dat, aes(x = xvar, y = yvar)) + geom_point(shape = 20, size = 1) +
geom_line(aes(x = xvar, y = yvar, group = gr), data = dat2)

Sample Image

Ggplotly clickable link in R plot

Following chapter 21 of the R plotly book you could achieve your desired result by passing the link via the customdata attribute and adding a custom event handler via ´htmlwidgets::onRender`. For the custom event handler you could simply use the JS code from the referenced link.

# Data frame
data <- data.frame(
check.names = FALSE,
`price` = c(6790000, 6950000, 5990000, 5990000, 4150000, 8654100),
`rooms` = c("4+1", "3+1", "2+kk", "2+1", "1+kk", "4+1"),
`m2` = c(78, 78, 58, 52, 30, 100),
`location` = c("Bohunice", "Bystrc", "Plotni", "Lesna", "Styrice", "Zabrdovice"),
`link` = c(
"https://www.sreality.cz/detail/prodej/byt/4+1/brno-bohunice-moldavska/2155567196",
"https://www.sreality.cz/detail/prodej/byt/3+1/brno-bystrc-cerneho/2881087836",
"https://www.sreality.cz/detail/prodej/byt/2+kk/brno--plotni/2840209756",
"https://www.sreality.cz/detail/prodej/byt/2+1/brno-lesna-triskalova/2905770332",
"https://www.sreality.cz/detail/prodej/byt/1+kk/brno-styrice-videnska/3682412892",
"https://www.sreality.cz/detail/prodej/byt/4+1/brno-zabrdovice-kornerova/2548312156"
)
)

library(ggplot2)
library(plotly)
library(htmlwidgets)

g <- ggplot(data, aes(
x = m2, y = price,
text = paste0(
"Type: ", rooms, "\n",
"Price: ", price, "\n",
"M2: ", m2, "\n",
"Location: ", location
),
customdata = link
)) +
geom_point(aes(fill = rooms), color = "black", size = 3, alpha = 0.9) +
theme_minimal() +
scale_x_continuous(breaks = seq(min(0), max(350), by = 50)) +
scale_y_continuous(breaks = seq(min(0), max(40000000), by = 2000000)) +
theme(
legend.title = element_blank()
)

p <- ggplotly(g, tooltip = c("text"))

onRender(
p, "
function(el) {
el.on('plotly_click', function(d) {
var url = d.points[0].customdata;
window.open(url);
});
}
"
)

Sample Image

Open Link on Datapoint Click with Plotly in R Shiny

Here is a scatterplot with points that open a link when they are clicked:

library(plotly)
library(htmlwidgets) # to use the 'onRender' function

dat <- iris[1:2,]
urls <- c("http://google.com", "https://stackoverflow.com")

p <- plot_ly(dat, type = "scatter", mode = "markers",
x = ~Sepal.Width, y = ~Sepal.Length,
customdata = urls)

js <- "
function(el, x) {
el.on('plotly_click', function(d) {
var point = d.points[0];
var url = point.data.customdata[point.pointIndex];
window.open(url);
});
}"

p %>% onRender(js)

Sample Image

Controlling order of points in ggplotly in R

Actually, I find that plotly creates the right order in this particular example even without changing the plot/ data frame in a first place.

library(tidyverse)
library(plotly)

set.seed(1)
mydf <- data.frame(x=rnorm(500), label = 'a', stringsAsFactors = FALSE) %>% mutate(y = rnorm(500)*0.1 + x)
mydf$label[50] <- "point"

ggplot(mydf) + geom_point(aes(x=x, y=y, color=label, size = label)) +
scale_size_manual(values = c(a = 0.1,point = 2))

plotly::ggplotly()

Sample Image

The safer option may probably be @Dinre 's answer of your aforementioned question - separate your data to different layers first. I am using the suggested quick base R subset as in the answer, but you can also split using split or with tidyverse functions.

df_layer_1 <- mydf[mydf$label=="a",]
df_layer_2 <- mydf[mydf$label=="point",]

ggplot() +
geom_point(data=df_layer_1, mapping = aes(x, y), colour="orange", size = .1) +
geom_point(data=df_layer_2, aes(x, y), colour="blue", size = 2)

plotly::ggplotly()

Sample Image

R version 3.6.0 (2019-04-26)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1

other attached packages:
[1] plotly_4.9.0 ggplot2_3.2.0


Related Topics



Leave a reply



Submit