[英]Tooltip inserting image and/or ggplot in plotly R
我想在 plotly 中创建的 3D UMAP 中编辑工具提示 hover 功能。 What I want to do is attach a saved image corresponding to a specific 'Sample.Code' and have that image appear when I hover over it in the 3D plotly scatter plot.
这将类似于此链接中附加的交互式 t-SNE/MNIST 数据集: https://dash.plotly.com/dash-core-components/tooltip
但是,上面写的是 python 而不是 R。 是否有可能在 R 中实现这一点?
我在下面附上了我的代码:
# load ggplot2
library(ggplot2)
library(hrbrthemes)
library(tidyverse)
library(dplyr)
library(wesanderson)
library(RColorBrewer)
library(manipulate)
library(umap)
library(plotly)
library(shiny)
library(leaflet)
#set wd to location where plots will be saved. First step is to upload the initial data.
dt <- read.csv('data.csv')
#Run to the UMAP
df <- as.matrix(dt[, 2:149]) #remember to only set columns which will be used in the UMAP calculation
custom.config = umap.defaults #manual settings
custom.config$n_components = 3
custom.config$n_neighbors = 8
custom.config$min_dist = 0.6
data_umap <-umap(df, config = custom.config)
data_raw<-as.data.frame(data_umap$layout)
data_plot <- cbind(data_raw, dt)
#running graphics script. Make sure to change color and size to appropriate labels
#This is the visual that will get manipulated playing around with the UMAP parameters
UMAP_plot <- ggplot(data_plot, aes(x = V1, y = V3, color = Dataset)) +
labs(title = '2D UMAP') +
geom_point(alpha = 0.7, shape =19 ) +
theme_light() +
theme(axis.text.y = element_text(size = 15),
axis.text.x = element_text(size = 10),
axis.title = element_text(size = 15),
plot.title = element_text(size = 17),
legend.text = element_text(size=15)) +
scale_radius(range=c(4, 10))
colors <- c('#4AC6B7', '#1972A4', '#965F8A', '#FF7070', 'darkolivegreen')
UMAP_2D <- plot_ly(data_plot, x= ~V1, y= ~V3, color = ~Dataset, colors=colors, type = "scatter", mode = "markers", text = ~paste('Sample.Code:', Sample.Code))
UMAP_3D <- plot_ly(data_plot, x= ~V1, y= ~V2, z= ~V3, type="scatter3d", mode="markers", color = ~Dataset, colors=colors, text = ~paste('Sample.Code:', Sample.Code))
UMAP_3D <- UMAP_3D %>% layout(title = '3D UMAP',
paper_bgcolor = 'grey',
plot_bgcolor = 'black')
UMAP_3D.update_layout(legend=dict(
yanchor="top",
y=0.99,
xanchor="left",
x=0.01
))
#Eventually add fingerprints to hover based on this code here: https://anchormen.nl/blog/data-science-ai/images-in-plotly-with-r/
print(UMAP_plot)
print(UMAP_2D)
print(UMAP_3D)
根据您的评论,我绝对可以使用 Plotly 示例中的数据。 我还没有购买 Dash,但您当然可以这样做并让自己更轻松。 (我想。我没用过;所以我猜。)
在没有 Dash 的情况下,使用 Python 示例,我基本上用 Plotly 在 R 中重新创建了该图。 我没有使用ggplot。
我使用了两个库,但我唯一一次使用htmlwidgets
时附加了库名称。
首先,数据是从与 Python 示例中相同的位置收集的,但我只使用了前 100 行。 接下来,我将换行标记添加到描述中。 SVG 文本中没有字符串换行。 每行都单独标记。 我用了 65 个字符,给出或接受一个完整的单词。 您可以根据您要查找的工具提示的大小对其进行修改。
之后,我创建了基本的 plot。 我将我可以添加的所有内容都添加到了工具提示中,因此我只需要进行一些调整。 Plotly 将所有内容呈现为工具提示中的文本,因此我添加了几个换行符 (18),以便为图像留出空间。 我还在工具提示中添加了一些样式(例如"darkblue"
文本)。
在 JS( htmlwidgets::onRender
中的所有内容)中,您需要收集工具提示中的内容,删除没有文本的换行符,并 retrofit 将图像 URL 作为<image>
元素。
这需要获得职位和可用空间。 这需要确定工具提示是否在点的左侧、点的右侧,或者文本是否在工具提示中居中。 对于有扩展描述的点,事情是不对的,所以也需要一些调整。 我在 JS 中添加了很多注释,所以这也应该解释很多代码的目的。
如果您有任何问题,请告诉我。
library(plotly)
# get molecular data
dp <- read.csv("https://raw.githubusercontent.com/plotly/dash-sample-apps/main/apps/dash-drug-discovery/data/small_molecule_drugbank.csv")
# because even SVG doesn't string wrap, each row is a separate tag
dp$desc <- gsub('(.{1,65})(\\s|$)', '\\1<br>', dp$DESC)
plt <- plot_ly(
dp[1:100, ], x = ~LOGP, y = ~PKA, mode = "markers", type = "scatter",
marker = list(colorscale = "Viridis",
color = ~MW, size = ~MW,
colorbar = list(title = "Molecule<br>Weight",
outlinewidth = 0), # just looks better without you!
line = list(color = "#444"),
reversescale = T, sizeref = 45,
sizemode = "diameter", opacity = .8),
customdata = ~IMG_URL,
text = ~NAME, hovertext = ~desc,
hovertemplate = paste0( # 'here' is used for regex in JS
"image href='%{customdata}' here ", # 18 <br> make space for image (see in JS where 18 matters)
"<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>",
"<span style='fill:darkblue;font-size:2em;'>%{text}</span><br>",
"<span>%{hovertext}</span><extra></extra>")) %>%
layout(xaxis = list(title = "Log P"), yaxis = list(title = "pkA"),
plot_bgcolor = "#1a1a1a", paper_bgcolor = "#0d0d0d", # almost and off black
hoverdistance = 10) %>% # more precision in selection
htmlwidgets::onRender("function(el){
console.log(el);
setInterval(function(){ /* no content when tip is called; keep looking */
tt = document.querySelector('#' + el.id + '> div > div > svg:nth-child(5) > g');
},100);
el.on('plotly_hover', function(d){
if(tt.firstChild) {
cvy = parseFloat(getComputedStyle(tt).fontSize); /* em to px conversion */
str = tt.innerHTML;
gimme = /image.*(?=( here \\<br))/.exec(str); /* extract image details */
x = /(?<=(data-notex=\"1\" x=\")).*(?=(\" y=.*data))/g.exec(str);/* image x */
y = /(?<=(y=\")).*(?=(\" data-unformatted))/g.exec(str); /* image y */
bc = tt.getBoundingClientRect();
wbc = bc.width;
hbc = bc.height;
if(/-/.exec(x[0])) wwbc = (wbc * -1) - Number(x[0]); /* adjust x if tip to the left */
if(/-/.exec(x[0]) === null) wwbc = Number(x[0]); /* adjust x if tip to the right */
if(x[0] == 0) wwbc = wbc * -.5; /* if text is centered */
ts = str.match(/\\<tspan?.*?\\/tspan\\>/gm); /* all tspans indexed */
dy = /(?<=(dy=\")).*(?=( x=))/g.exec(ts[18]); /* 18th break in the template (18 br's coded) */
dyc = /.*(?=(em))/.exec(dy[0]); /* collect digits; remove units */
cdy = cvy * Number(dyc[0]); /* convert em to px for image ht */
if(cdy > hbc * .75) cdy = hbc * .65; /* if em => px is larger than plot, reduce */
wbcw = wbc - Math.abs(Number(x[0]) * 2); /* get width for image */
if(ts.length >= 34) {
y[0] = Number(y[0]) * 1.1; /* lots of text images are low & too large */
cdy = cdy * .9;
}
beg = str.match(/.*(?=(\\<text))/); /* everything up to text tags */
jn = '\\<' + gimme[0] + ' x=\"' + wwbc + '\" y=\"' + y[0]; /* the image; can't crtl aspect ratio——Plotly-ism? */
jn = jn + '\" height=\"' + cdy + '\" width=\"' + wbcw +'\"\\/\\>';
tx = str.match(/\\<text.*pre\\;\"\\>?/); /* text element before tspan */
nts = ts.slice(18, ts.length).join('\\<\\/tspan\\>'); /* reassemble kept tspans */
clt = '\\<\\/text\\>\\<\\/g\\>'; /* closing tags */
altog = beg[0] + jn + tx[0] + nts + clt; /* put it together */
tt.innerHTML = altog; /* replace tooltip */
}
});
}")
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.