首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用ggvis显示信息

使用ggvis显示信息
EN

Stack Overflow用户
提问于 2015-01-17 04:14:12
回答 2查看 641关注 0票数 1

我正在开发一个使用ggvis图的闪亮的应用程序。我正在尝试在鼠标移动到图形上的一个点上时显示信息。如果我使用layer_points,关于特定点的数据可以正确显示。但是,如果我使用layer_bars,那么即使数据集没有更改,它也会显示值为NULL

代码语言:javascript
复制
dfL %>% ggvis(x = ~time, y = ~amount) %>% layer_points() 
%>% add_tooltip(all_values, "hover") %>% bind_shiny("AnPlot", "AnPlot_ui")

^信息正确显示。

代码语言:javascript
复制
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的代码。

代码语言:javascript
复制
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。我试图在这里只提供相关的代码,但如果其他部分是必要的,我将编辑该帖子并将其包括在内。

我不明白为什么当图表是散点图时,它会返回正确的值,但当它是条形图时,却无法返回这些值。

感谢您能提供的任何见解!

EN

回答 2

Stack Overflow用户

发布于 2015-01-17 07:10:31

这是一个棘手的问题,因为不幸的是,并不是所有类型的layer都能像layer_points一样很好地处理add_tooltip。我不是100%清楚许多ggvis函数的所有实现细节,但我至少会向您介绍我对它的理解,以便您可以看到我是如何得出我的解决方案的。我将使用cars数据集(默认情况下在您的会话中可用)进行演示,但是您只需进行一些细微的调整,即可将该方法应用于您自己的数据。

代码语言:javascript
复制
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的数据对象的名称。

代码语言:javascript
复制
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,我们有:

代码语言:javascript
复制
point_obj %>% add_tooltip(vis_names,"hover")

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

代码语言:javascript
复制
bar_obj %>% add_tooltip(vis_names,"hover")

它们绝对不是my_data中的列名。如果我们定义另一个函数,

代码语言:javascript
复制
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 />")
}

我们可以获得更多细节:

代码语言:javascript
复制
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一起使用

代码语言:javascript
复制
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工具提示函数那么简洁,但它可以完成工作。这一行

代码语言:javascript
复制
bar_obj <- get("bar_obj",.GlobalEnv)

从全局环境中获取我们实际绘制的ggvis对象的副本,并将其放入工具提示子函数的作用域中。接下来两行,

代码语言:javascript
复制
input_data <- get_data(bar_obj)[[1]]
bar_data <- get_data(bar_obj)[[4]]  

存储我们的输入数据集(相当于my_data)和绘图中使用的条形图坐标,即我们可以通过变量x访问的内容。xmin_col是定义条形图左侧x坐标的值列。通过将其与x中包含的xmin_值进行比较,我们可以确定绘制的是哪行数据,即

代码语言:javascript
复制
row_idx <- which.min(abs(x[1,1]-xmin_col))

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

无论如何,我们可以使用我们创建的row_idx来提取由我们悬停在其上的栏(即x包含的内容)表示的原始数据行,这是在paste0(...)部件中完成的。结果如下所示:

代码语言:javascript
复制
bar_obj %>% add_tooltip(tooltip_bars,"hover") 

由于某些原因,标签的格式不正确;尽管这不应该与我使用的一般方法有任何关系。

因此,回到最初关于为什么显示NULL值的问题,简短的答案是在layer_points可视化中传递给add_tooltip的数据对象与在layer_bars可视化中传递给它的数据对象不同,因此调用x$amountx$pv将返回NULL,因为这些列在x中不存在。

为了清楚起见,要将此代码应用于您自己的数据,请确保您像我对bar_obj所做的那样创建了一个基本ggvis对象,并在tooltip_bars函数的get("bar_obj",.GlobalEnv)行中使用"bar_obj"替换它的名称。

票数 2
EN

Stack Overflow用户

发布于 2015-01-20 13:18:12

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

代码语言:javascript
复制
  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))
  }

其中输入数据已经在反应函数中定义,例如

代码语言:javascript
复制
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函数中调用了工具提示函数:

代码语言:javascript
复制
  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,因为它是绘图中的一部分数据。但是,我发现如果不显式设置该参数,工具提示就不会出现。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27992078

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档