我正在尝试使用滑块来控制纵向空间数据集中的年份,基本上是一组散点图.我无法弄清楚如何将滑块分配给这个变量 - 你能用ggvis做到吗?
简化的数据集:
data <- data.frame(year=rep(2000:2002, each=23),
x=rnorm(23*3,10), y=rnorm(23*3,10),
count=c(rnorm(23,2), rnorm(23,4), rnorm(23,6)))
Run Code Online (Sandbox Code Playgroud)
我尝试过的:
### This is what is looks like in ggplot2, I'm aiming to be able to toggle
### between these panels
ggplot(data, aes(x, y, size=count)) + geom_point() + facet_grid(~year)
### Here is where I'm at with ggvis
data %>%
ggvis(~x, ~y, size=~count) %>%
layer_points()
# I'm not sure how to assign a variable (year) to a slider, I've been trying
# within the layer_points() function
### I also tried using the props() function, but I don't fully understand
### how to use it.
data %>%
ggvis(~x, ~y, size=~count) %>%
layer_points() %>%
props(prop("fill", input_slider(min(data$year), max(data$year)))) #error message
Run Code Online (Sandbox Code Playgroud)
任何帮助表示赞赏!
我不确定您是否要将滑块用于filter
数据点(即仅显示滑块上所选年份的那些点),或者根据滑块的值显示不同颜色的年份.
data %>%
ggvis(~x, ~y, size=~count) %>%
layer_points(opacity=input_slider(min(data$year), max(data$year), step=1,
map=function(x) ifelse(data$year == x, 1, 0)))
Run Code Online (Sandbox Code Playgroud)
data %>%
ggvis(~x, ~y, size=~count) %>%
layer_points(fill=input_slider(min(data$year), max(data$year), step=1,
map=function(x) factor(x == data$year)))
Run Code Online (Sandbox Code Playgroud)
left_right()
函数.在第一次编辑中,我提出了一个没有被恰当地视为包装的解决方案.我有兴趣创建一个返回的反应对象的包装器left_right()
,避免create_keyboard_event
一起修改.
在R中读取了ggvis
更彻底和更多关于S4对象的源代码之后,我意识到是的,你可以简单地包装一个被动对象,只要你适当地保存broker
类和它的broker
属性.
这允许我们编写更优雅的代码,例如:
year_lr <- left_right(1997, 2002, value=2000, step=1)
year_wrapper <- reactive({
as.numeric(year_lr() == data$year)
})
class(year_wrapper) <- c("broker", class(year_wrapper))
attr(year_wrapper, "broker") <- attr(year_lr, "broker")
data %>%
ggvis(~x, ~y, size=~count) %>%
layer_points(opacity:=year_wrapper)
Run Code Online (Sandbox Code Playgroud)
left_right()
功能user3389288问我一个很好的问题,因为你没有函数map
参数left_right()
,你怎么能实际绑定键盘事件来生成自定义参数.例如,在这个问题的背景下,我们如何定制left_right()
为年度过滤器?
如果你深入研究源代码ggvis
,你可以看到这left_right()
只是一个瘦的包装函数调用create_keyboard_event
.
因此,我们可以创建自己的版本left_right()
,甚至可以h_j_k_l()
说如果你对Vi很狂热.但是,这里有一个很大但是,如果你进一步挖掘一层来看看它的实现create_keyboard_event
,你会发现它不太适合我们的任务.
这是因为为了显示一些点,而隐藏其他点,我们必须让它left_right
返回一个vector
(等于行数data
).但是,这两个left_right
和create_keyboard_event
与假定返回值(其也是的当前状态产生value
由左/右改性键按压)是标量.
为了将返回值(向量)与缓存的当前状态(标量,即年份)分开,我们必须创建一个稍微修改过的版本left_right()
和create_keyboard_event
.
以下是可行的源代码.
data <- data.frame(year=rep(1997:2002, each=12),
x=rnorm(24*3,10), y=rnorm(24*3,10),
count=c(rnorm(24,2), rnorm(24,4), rnorm(24,6)))
create_keyboard_event2 <- function(map, default.x = NULL, default.res = NULL) {
# A different version of ggvis::create_keyboard_event function:
# the major different is that the map function returns a list,
# list$x is the current value and list$res the result (returned to a ggvis prop).
# this seperation allows us to return a vector of different
# values instead of a single scalar variable.
if (!is.function(map)) stop("map must be a function")
vals <- shiny::reactiveValues()
vals$x <- default.x
vals$res <- default.res
# A reactive to wrap the reactive value
res <- reactive({
vals$res
})
# This function is run at render time.
connect <- function(session, plot_id) {
key_press_id <- paste0(plot_id, "_key_press")
shiny::observe({
key_press <- session$input[[key_press_id]]
if (!is.null(key_press)) {
# Get the current value of the reactive, without taking a dependency
current_value <- shiny::isolate(vals$x)
updated <- map(key_press, current_value)
vals$x <- updated$x
vals$res <- updated$res
}
})
}
ggvis:::connector_label(connect) <- "key_press"
spec <- list(type = "keyboard")
ggvis:::create_broker(res, connect = connect, spec = spec)
}
# a modified version of left_right. this closure encapsulates the
# data "year", allowing us to perform comparison of the current state of
# left_right (numeric year number) to the year vector.
left_right_year <- function(min, max, value = (min + max) / 2,
step = (max - min) / 40, year) {
# Given the key_press object and current value, return the next value
map <- function(key_press, current_value) {
key <- key_press$value
print(current_value)
if (key == "left") {
new_value <- pmax(min, current_value - step)
} else if (key == "right") {
new_value <- pmin(max, current_value + step)
} else {
new_value = current_value
}
list(x=new_value, res=as.numeric(year == new_value))
}
create_keyboard_event2(map, value, as.numeric(value==year))
}
# now with an additional argument, the data$year
alpha_by_year <- left_right_year(1997, 2002, value=2000, step=1, data$year)
data %>%
ggvis(~x, ~y, size=~count) %>%
layer_points(opacity:=alpha_by_year) # if you let left_right_year return
# a factor vector, you can use fill:=... as well
Run Code Online (Sandbox Code Playgroud)
你可以比较left_right_year
和create_keyboard_event2
与他们的香草版本的同行.
例如,原文create_keyboard_event
是:
create_keyboard_event <- function(map, default = NULL) {
if (!is.function(map)) stop("map must be a function")
vals <- shiny::reactiveValues()
vals$x <- default
# A reactive to wrap the reactive value
res <- reactive({
vals$x
})
# This function is run at render time.
connect <- function(session, plot_id) {
key_press_id <- paste0(plot_id, "_key_press")
shiny::observe({
key_press <- session$input[[key_press_id]]
if (!is.null(key_press)) {
# Get the current value of the reactive, without taking a dependency
current_value <- shiny::isolate(vals$x)
vals$x <- map(key_press, current_value)
}
})
}
connector_label(connect) <- "key_press"
spec <- list(type = "keyboard")
create_broker(res, connect = connect, spec = spec)
}
Run Code Online (Sandbox Code Playgroud)
您可以看到我们的修改版本不仅会缓存当前状态vals$x
,还会缓存返回向量vals$res
.
变量vals
是一个无功值.这个概念来自Shiny.您可以查看本文档,了解一般反应值和反应性的高级概述.
因为vals$x
它本身就是一个反应值.直觉,如果
x <- left_right(1, 100, value=20, step=10)
Run Code Online (Sandbox Code Playgroud)
然后
y <- reactive(x() * 2)
Run Code Online (Sandbox Code Playgroud)
应该允许我们实现快速map
功能.
但是它没有按预期工作.我还没弄清楚为什么.如果您知道答案,请告诉我!
更新:cf EDIT2
归档时间: |
|
查看次数: |
1587 次 |
最近记录: |