You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让R中Plotly树状图hover时显示节点自定义信息?

实现树状图节点/分支悬停显示自定义Label和State信息

问题背景

已用R完成历史工作流树状图的基础渲染,需要实现鼠标悬停在节点或分支位置时,显示actions列表中对应的自定义label和state信息。

解决方案

核心思路是将自定义的label和state数据关联到ggdendro生成的树状图数据中,通过ggplot的text美学映射定义悬停内容,最后用ggplotly启用悬停提示。

修改后的完整代码

library(plotly)
library(ggplot2)
library(ggdendro)
library(shiny)

find_lca <- function(parents, depth, node1, node2) {
  # Find the depths of the nodes
  depth1 <- depth[node1]
  depth2 <- depth[node2]
  
  # Make sure node1 is at a higher depth
  if (depth1 < depth2) {
    temp <- node1
    node1 <- node2
    node2 <- temp
  }
  
  # Adjust the depth of node1
  depth_diff <- depth1 - depth2
  while (depth_diff > 0) {
    node1 <- parents[node1]
    depth_diff <- depth_diff - 1
  }
  
  # Check if node1 and node2 are already the same
  if (node1 == node2) {
    return(node1)
  }
  
  # Move up both nodes until they have a common parent
  while (parents[node1] != parents[node2]) {
    node1 <- parents[node1]
    node2 <- parents[node2]
  }
  
  # Return the lowest common ancestor
  return(parents[node1])
}

calculate_distance <- function(parent.of.index, distance.from.root, child_a_index, child_b_index) {
  
  # Calculate the distance between root and n1
  dist_n1_root <- distance.from.root[[child_a_index]]
  # Calculate the distance between root and n2
  dist_n2_root <- distance.from.root[[child_b_index]]
  
  # Calculate the distance between n1 and n2
  dist_n1_n2 <- distance.from.root[[find_lca(parent.of.index, distance.from.root, child_a_index, child_b_index)]]
  # Calculate the final distance using the formula
  final_distance <- dist_n1_root + dist_n2_root - 2 * dist_n1_n2
  
  return(final_distance)
}


state <- list(1, 2, 3, 4, 5)
actions = list( list(label = "Action 1", variables = state[1]), 
                list(label = "Action 2", variables = state[2]), 
                list(label = "Action 3", variables = state[3]), 
                list(label = "Action 4", variables = state[4]), 
                list(label = "Action 5", variables = state[5]) 
)
parent.of.index = c(-1, 1, 1, 3, 3)
depth = c(0, 1, 1, 2, 2)

dendro_data <- data.frame(
  child_b = c()
)


for (i in 2:length(actions)) {
  for (j in 1:(i-1)) {
    child_a <- i
    child_b <- j
    #child_b is ALWAYS smaller/higher/earlier than child_a
    distance <- calculate_distance(parent.of.index, depth, child_a, child_b)
    dendro_data[i, j] = distance
  }
}

dendro_data <- dendro_data[-1, ]
colnames(dendro_data) <- state[-length(state)]

temp = as.vector(na.omit(unlist(dendro_data)))
NM = unique(c(colnames(dendro_data), row.names(dendro_data)))
mydist = structure(temp, Size = length(NM), Labels = NM,
                   Diag = FALSE, Upper = FALSE, method = "euclidean", #Optional
                   class = "dist")
model <- hclust(mydist)
dhc <- as.dendrogram(model)

# 提取树状图完整数据(含线段和节点)
data <- dendro_data(dhc, type = "triangle")

# 处理节点数据,关联自定义label和state
node_data <- data$label
node_data$state <- as.integer(node_data$label)
# 匹配actions中的自定义信息
node_data <- merge(node_data, 
                   do.call(rbind, lapply(actions, function(x) data.frame(label = x$label, state = unlist(x$variables)))),
                   by = "state", all.x = TRUE)

# 处理线段数据,关联对应子节点的自定义信息
segment_data <- data$segment
segment_data <- merge(segment_data, node_data[, c("x", "label", "state")], by.x = "x", by.y = "x", all.x = TRUE)

# 绘制树状图并添加悬停文本
p <- ggplot() + 
  # 分支线段添加悬停信息
  geom_segment(data = segment_data, 
               aes(x = x, y = y, xend = xend, yend = yend,
                   text = paste("Label:", label, "\nState:", state))) + 
  # 节点标签添加悬停信息
  geom_text(data = node_data, 
            aes(x = x, y = y, label = label,
                text = paste("Label:", label, "\nState:", state))) +
  scale_y_reverse(expand = c(0.2, 0)) +
  theme_dendro()

# 启用悬停提示,指定显示自定义文本内容
ggplotly(p, tooltip = "text")

关键修改说明

  • 数据关联:将node_data与actions中的label、state匹配,确保每个节点对应到自定义信息
  • 悬停文本定义:在geom_segment和geom_text的美学映射中加入text参数,用paste组合多行提示内容
  • 悬停启用:调用ggplotly时指定tooltip = "text",让Plotly渲染自定义的悬停提示

内容的提问来源于stack exchange,提问作者LinguiniThePasta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 03:27:06