我正在使用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
有三列:时间,pv和金额。我试图在这里只提供相关代码,但如果需要其他部分,我会编辑帖子并将其包含在内。
我无法弄清楚为什么当图表是散点图时它会返回正确的值,但是当它是条形图时无法返回值。
感谢您提供的任何见解!
答案 0 :(得分:2)
这是一个棘手的问题,因为很遗憾,并非所有类型的layer
与add_tooltip
的{{1}}一样好。我不是100%清楚许多layer_points
函数的所有实现细节,但我至少会引导您理解它,以便您了解我是如何达到我的解决方案的。我将使用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_
显然是我们正在悬停的给定栏的x坐标,而xmax_
和stack_upr_
是相应的y坐标。从这里开始,我们只需要一种方法将条形坐标转换回原始输入数据stack_lwr_
。
在my_data
中,我经常使用一个称为ggplot2
的简洁函数。当您在ggplot_build
对象上调用此函数时,它会创建绘图(就像打印通常那样),但也会返回有关构建绘图的所有内容的非常详细的信息 - 长轴范围,短轴范围等...当您需要找到有关图表的非常精确的信息时,这非常有用。我怀疑ggplot
会有类似ggvis
的内容,并通过小插图发现函数ggplot_build
。在get_data
对象上调用此方法会返回ggvis
个列表,其中第一个元素是原始data.frame
(data.frame
),第四个元素是{{1其中包含上面条形图中显示的四列 - 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坐标的值列。通过将此值与x
中包含的xmin_col
值进行比较,我们可以确定正在绘制哪一行数据,即
xmin_
对于此示例,可能有一种更简单的方法可将我们的值x
与列row_idx <- which.min(abs(x[1,1]-xmin_col))
进行比较,以确定当前正在悬停的数据行。我使用上面的x[1,1]
方法,因为我认为在例如xmin_
值不完全是某个整数+ 0.5的情况下它会更强大,因为它们处于这种情况。试图测试浮点数之间的精确相等有时会有问题。
无论如何,我们可以使用我们创建的which.min(...)
来提取我们正在悬停的栏所代表的原始数据行(即xmin_
包含的内容),这是在{{{ 1}}部分。结果如下:
row_idx
由于某种原因,标签格式不正确;虽然这与我使用的一般方法没有任何关系。
回到原始问题,关于为什么显示x
值,简短的回答是传递给paste0(...)
可视化中的bar_obj %>% add_tooltip(tooltip_bars,"hover")
的数据对象不一样正如在NULL
可视化中传递给它的内容一样,因此调用add_tooltip
和layer_points
将返回layer_bars
,因为x$amount
中没有这些列。
为了澄清一下,要将此代码应用于您自己的数据,请确保您创建一个基本x$pv
对象,就像我使用NULL
一样,并将其名称替换为我使用的{{1} } x
函数的ggvis
行。
答案 1 :(得分:0)
我遇到了类似的问题。我通过显式过滤数据集到悬停所属的行来解决它,如:
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
,因为它是图中的一条数据,因此不清楚。但是,我发现如果没有明确设置该参数,工具提示就不会出现。