R 使用ggvis显示信息

R 使用ggvis显示信息,r,ggvis,R,Ggvis,我正在使用ggvis图形开发一个闪亮的应用程序。我试图在鼠标移动到图形上的某个点上时显示信息。如果我使用图层点,则有关特定点的数据将正确显示。但是,如果我使用图层条,则即使数据集未更改,也会显示值为NULL dfL %>% ggvis(x = ~time, y = ~amount) %>% layer_points() %>% add_tooltip(all_values, "hover") %>% bind_shiny("AnPlot", "AnPlot_ui")

我正在使用ggvis图形开发一个闪亮的应用程序。我试图在鼠标移动到图形上的某个点上时显示信息。如果我使用
图层点
,则有关特定点的数据将正确显示。但是,如果我使用
图层条
,则即使数据集未更改,也会显示值为
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")
^接收空值

以下是
所有值的代码

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 />")
}

all_value这是一个棘手的问题,因为不幸的是,并非所有类型的
图层
s都能像
图层点
那样很好地处理
添加工具提示
。我对许多
ggvis
函数的所有实现细节都不是100%清楚,但我至少会让您了解我对它的理解,以便您了解我是如何得出解决方案的。我将使用
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
add_tooltip
的内部打印出名称是一个很好的方法,可以准确地了解传递的数据。对于
点_obj
,我们有:

point_obj %>% add_tooltip(vis_names,"hover")

这是我输入数据的列名。另一方面,对
bar_obj
执行此操作将为我们提供:

bar_obj %>% add_tooltip(vis_names,"hover")

绝对不是
my\u 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 />")
}

因此
xmin_
xmax_
显然是我们悬停的给定条的x坐标,而
stack\u upr\u
stack\u lwr\u
是各自的y坐标。从这里开始,我们只需要一种将条形坐标转换回原始输入数据的方法,
my_data

ggplot2
中,我经常使用一个整洁的函数,名为
ggplot\u build
。当您在
ggplot
对象上调用此函数时,它会创建打印(就像打印通常所做的那样),但也会返回有关构建打印的所有内容的详细信息—长轴范围、短轴范围等。。。当您需要查找有关图形的非常精确的信息时,这非常有用。我怀疑
ggvis
会有类似于
ggplot\u build
的功能,通过这个小插曲,我找到了函数
get\u data
。在
ggvis
对象上调用此函数将返回
data.frame
s列表,其中第一个元素是原始的
data.frame
my_data
),第四个元素是
data.frame
,其中包含上面条形图中显示的四列-
xmin
xmax
stack\u upr\uu
stack\u lwr\uu

从这里,我将定义一个最终函数,该函数将被传递到
add\u tooltip
,用于
bar\u 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 />")
}
从全局环境中获取实际绘制的
ggvis
对象的副本,并将其拉入工具提示子功能的范围。接下来的两行

input_data <- get_data(bar_obj)[[1]]
bar_data <- get_data(bar_obj)[[4]]  
对于本例,可能有一种更简单的方法将我们的值
x[1,1]
与列
xmin\uu
进行比较,以确定当前悬停的数据行。我使用了上面的
which.min(…)
方法,因为我认为在这种情况下,
xmin\uu
值不完全是某个整数+0.5的情况下,它会更加健壮。尝试测试浮点数之间的精确相等有时可能会有问题

无论如何,我们可以使用我们创建的
row\u idx
来提取由我们悬停在上面的条表示的原始数据行(即
x
包含的内容),这是在
paste0(…)
部分完成的。结果如下所示:

bar_obj %>% add_tooltip(tooltip_bars,"hover") 

由于某些原因,标签格式不正确;虽然这与我使用的一般方法无关

回到您最初的问题,关于为什么显示
NULL
值,简短的回答是在
层中传递给
add\u工具提示的数据对象与在
层条中传递给它的数据对象不同,因此调用
x$amount
x$pv
将返回
NULL
,因为这些列在
x
中不存在


为了澄清这一点,要将此代码应用于您自己的数据,请确保您创建了一个基本的
ggvis
对象,就像我使用
bar\u obj
一样,并在
get(“bar\u obj,.GlobalEnv)
工具提示栏
函数的
行中使用了它的名称。

我遇到了类似的问题。我通过显式过滤悬停所属行的数据集来解决此问题,如:

  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))
  }

在我的示例中,从中不清楚是否需要键入
bin
,因为它是绘图中的数据片段之一。但是,我发现如果没有明确设置该参数,工具提示将不会出现。

谢谢您的详细回答。然而,我在实现它时遇到了一些问题。我创建了一个基本的
ggvis
对象:
layer\u条(x=~time,y=~pv,fill:=“#b0b0”)
。然后我更新了
工具提示栏
工具提示栏%bind\u闪亮(“AnPlot”、“AnPlot\u ui”)
。当我运行应用程序时,图形显示,但当我悬停时,我收到此错误
警告:在observer:object'levelAn_obj'中未找到未处理的错误
。谢谢你的帮助!更正,我看到我没有完全复制上述评论中的对象。
ggvis
对象是
levelAn\u obj%ggvis(x=~time,y=~amount)%%>%layer\u bars()%%>%layer\u bars(x=~tim
input_data <- get_data(bar_obj)[[1]]
bar_data <- get_data(bar_obj)[[4]]  
row_idx <- which.min(abs(x[1,1]-xmin_col))
bar_obj %>% add_tooltip(tooltip_bars,"hover") 
  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
})
  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