我正在开发一个使用ggvis图的闪亮的应用程序。我正在尝试在鼠标移动到图形上的一个点上时显示信息。如果我使用layer_points,关于特定点的数据可以正确显示。但是,如果我使用layer_bars,那么即使数据集没有更改,它也会显示值为NULL。
dfL %>% ggvis(x = ~time, y = ~amount) %>% layer_points()
%>% add_tooltip(all_values, "hover") %>% bind_shiny("AnPlot", "AnPlot_ui")^信息正确显示。
dfL %>% ggvis(x = ~time, y = ~amount) %>% layer_bars(width=1, fill:= "white")
%>% add_tooltip(all_values, "hover") %>% bind_shiny("AnPlot", "AnPlot_ui")^接收值为NULL。
以下是all_values的代码。
all_values <- function(x) {
if(is.null(x)) return(NULL)
paste0("Amount: ", format(x$amount, digits=4),
" Present Value: ", format(x$pv, digits=4), collapse = "<br />")
}数据帧dfL有三列: time、pv和amount。我试图在这里只提供相关的代码,但如果其他部分是必要的,我将编辑该帖子并将其包括在内。
我不明白为什么当图表是散点图时,它会返回正确的值,但当它是条形图时,却无法返回这些值。
感谢您能提供的任何见解!
发布于 2015-01-17 07:10:31
这是一个棘手的问题,因为不幸的是,并不是所有类型的layer都能像layer_points一样很好地处理add_tooltip。我不是100%清楚许多ggvis函数的所有实现细节,但我至少会向您介绍我对它的理解,以便您可以看到我是如何得出我的解决方案的。我将使用cars数据集(默认情况下在您的会话中可用)进行演示,但是您只需进行一些细微的调整,即可将该方法应用于您自己的数据。
library(dplyr)
library(ggvis)
##
my_data <- cars %>%
group_by(speed) %>%
summarize(avg_dist = mean(dist))
##
R> my_data
Source: local data frame [19 x 2]
speed avg_dist
1 4 6.00000
2 7 13.00000
3 8 16.00000
4 9 10.00000
5 10 26.00000
6 11 22.50000
7 12 21.50000
8 13 35.00000
9 14 50.50000
10 15 33.33333
11 16 36.00000
12 17 40.66667
13 18 64.50000
14 19 50.00000
15 20 50.40000
16 22 66.00000
17 23 54.00000
18 24 93.75000
19 25 85.00000我还将使用这个分组的数据定义两个可视化:bar_obj (条形图)和point_obj (散点图);以及一个函数vis_names,它只打印出传递给add_tooltip的数据对象的名称。
bar_obj <- my_data %>%
ggvis(x = ~speed, y = ~avg_dist) %>%
layer_bars()
##
point_obj <- my_data %>%
ggvis(x = ~speed, y = ~avg_dist) %>%
layer_points()
##
vis_names <- function(x) {
if(is.null(x)) return(NULL)
paste0(names(x),collapse="<br />")
}从add_tooltip内部打印出名称是一种很好的方法,可以准确地找出传递的是什么数据。对于point_obj,我们有:
point_obj %>% add_tooltip(vis_names,"hover")

它们是我的输入数据的列名。另一方面,为bar_obj执行此操作将为我们提供:
bar_obj %>% add_tooltip(vis_names,"hover")

它们绝对不是my_data中的列名。如果我们定义另一个函数,
bar_info <- function(x) {
if(is.null(x)) return(NULL)
paste(
names(x)[1],
x[1,1],
names(x)[2],
x[1,2],
names(x)[3],
x[1,3],
names(x)[4],
x[1,4],
sep=" : ",
collapse="<br />")
}我们可以获得更多细节:
bar_obj %>% add_tooltip(bar_info,"hover")

因此,xmin_和xmax_显然是我们悬停在其上的给定条形图的x坐标,而stack_upr_和stack_lwr_是各自的y坐标。在这里,我们只需要一种将条形图坐标转换回原始输入数据my_data的方法。
在ggplot2中,有一个我经常使用的很好的函数,叫做ggplot_build。当您在ggplot对象上调用此函数时,它会创建绘图(就像打印通常所做的那样),但也会返回有关构建绘图的所有内容的详细信息-长轴范围、短轴范围等。当你需要找出关于你的图表的非常精确的信息时,这是非常有用的。我怀疑ggvis会有类似于ggplot_build的东西,然后通过小插图我发现了函数get_data。在ggvis对象上调用此函数将返回data.frame的列表,其中第一个元素是原始data.frame (my_data),第四个元素是一个data.frame,其中包含上述条形图中所示的四列- xmin_、xmax_、stack_upr_和stack_lwr_。
接下来,我将定义最后一个函数,该函数将被传递给add_tooltip,以便与bar_obj一起使用
tooltip_bars <- function(x) {
if(is.null(x)) return(NULL)
bar_obj <- get("bar_obj",.GlobalEnv)
input_data <- get_data(bar_obj)[[1]]
bar_data <- get_data(bar_obj)[[4]]
xmin_col <- bar_data[,3]
row_idx <- which.min(abs(x[1,1]-xmin_col))
paste0(
paste0(names(input_data)[1],
": ",
format(input_data[row_idx,1],4)),
paste0(names(input_data)[2],
": ",
format(input_data[row_idx,2],4)),
collapse = "<br />")
}这里有很多功能-它当然不像all_values工具提示函数那么简洁,但它可以完成工作。这一行
bar_obj <- get("bar_obj",.GlobalEnv)从全局环境中获取我们实际绘制的ggvis对象的副本,并将其放入工具提示子函数的作用域中。接下来两行,
input_data <- get_data(bar_obj)[[1]]
bar_data <- get_data(bar_obj)[[4]] 存储我们的输入数据集(相当于my_data)和绘图中使用的条形图坐标,即我们可以通过变量x访问的内容。xmin_col是定义条形图左侧x坐标的值列。通过将其与x中包含的xmin_值进行比较,我们可以确定绘制的是哪行数据,即
row_idx <- which.min(abs(x[1,1]-xmin_col))对于本例,可能有一种更简单的方法来将值x[1,1]与列xmin_进行比较,以确定当前悬停在其上的数据行。我使用上面的which.min(...)方法是因为我认为在xmin_值不是某个整数+ 0.5的情况下,例如在这种情况下,它会更健壮。尝试测试浮点数之间的精确相等有时可能是有问题的。
无论如何,我们可以使用我们创建的row_idx来提取由我们悬停在其上的栏(即x包含的内容)表示的原始数据行,这是在paste0(...)部件中完成的。结果如下所示:
bar_obj %>% add_tooltip(tooltip_bars,"hover")

由于某些原因,标签的格式不正确;尽管这不应该与我使用的一般方法有任何关系。
因此,回到最初关于为什么显示NULL值的问题,简短的答案是在layer_points可视化中传递给add_tooltip的数据对象与在layer_bars可视化中传递给它的数据对象不同,因此调用x$amount和x$pv将返回NULL,因为这些列在x中不存在。
为了清楚起见,要将此代码应用于您自己的数据,请确保您像我对bar_obj所做的那样创建了一个基本ggvis对象,并在tooltip_bars函数的get("bar_obj",.GlobalEnv)行中使用"bar_obj"替换它的名称。
发布于 2015-01-20 13:18:12
我遇到了类似的问题。我通过显式地将数据集过滤到悬停所属的行来解决它,如下所示:
my_tooltip <- function(x) {
# do some checks
if (is.null(x)) return(NULL)
if (is.null(x$bin)) return(NULL)
# select the data for the bar you're hovered over
all_data <- my.data()
this_data <- all_data[all_data$bin == x$bin, ]
paste0("<b>", this_data$bin, ": ", "</b><br>", format(this_data$value))
}其中输入数据已经在反应函数中定义,例如
my_data <- reactive({
df <- df.all # simplest example
df <- df.all[df.all$group==input$selected_group,] # example using user input
})给定的names(df.all)是"group" "bin" "value"。
然后,我在反应式vis函数中调用了工具提示函数:
vis <- reactive({
plot.data %>%
ggvis(x=~bin, y=~value, key := ~bin) %>% # key on `bin` here
layer_bars(width=1, fill=~group) %>%
add_tooltip(my_tooltip, "hover")
})
vis %>% bind_shiny("my_plot") # bind with UI name在我的示例中,documentation不清楚您是否需要键入bin,因为它是绘图中的一部分数据。但是,我发现如果不显式设置该参数,工具提示就不会出现。
https://stackoverflow.com/questions/27992078
复制相似问题