Data 304: Visualzing Data and Models
The basic building block in Vega-Lite’s grammar of interaction.
2 types:
Can be used throughout the remainder of the chart specification
Can also optionally be bound to input widgets (e.g., sliders or drop down menus).
property | type | description |
---|---|---|
name | string | required; unique name for the parameter |
value | any | initial value; default is undefined |
bind | binding | binds the paramter to an input element (slider, radio buttons, etc.) |
expr | expression | This expression may include other parameters, in which case the parameter value will automatically update in reponse to changes in the other parameters. |
height
, width
, padding
, autosize
, background
(can be redefined as user parameters)datum
, item
, event
, parent
(may not be redefined, but may be used)cursor
(for geting information about cursor location)[1] "vl_bind_checkbox_input" "vl_bind_direct_input" "vl_bind_input"
[4] "vl_bind_radio_input" "vl_bind_range_input" "vl_bind_select_input"
We’ve seen range inputs before, but here is a different (perhaps silly) use case.
Steps:
vl_add_aparameter()
vl_bind_range_input()
list(expr = "...")
penguins_scatter |>
vl_add_parameter("width", value = 200) |>
vl_add_parameter("height", value = 200) |>
vl_bind_range_input("width", min = 100, max = 400, step = 1) |>
vl_bind_range_input("height", min = 100, max = 400, step = 1) |>
vl_add_properties(
width = list(expr = "width"),
height = list(expr = "height")
)
Here we use a dropdown to filter the data set to one species.
Here we use the legend to highlight one species. We’ll talk about “condition” shortly.
2 types:
[1] "vl_add_interval_selection" "vl_add_point_selection"
[3] "vl_config_selection"
vl_config_selection()
can be used to set defaults for point and interal selections.
Note: The default behavior of empty = TRUE
means that an empty selection selects everything.
Note: Here we set empty = FALSE
so an empty selection selects nothing.
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"height": 250,
"width": 400,
"mark": {
"type": "rect"
},
"encoding": {
"x": {
"field": "Origin",
"type": "nominal"
},
"y": {
"field": "Cylinders",
"type": "ordinal"
},
"color": {
"condition": {
"param": "selection",
"aggregate": "count",
"empty": false
},
"value": "gray"
}
},
"data": {
"url": "https://cdn.jsdelivr.net/npm/vega-datasets@v1.29.0/data/cars.json"
},
"params": [
{
"name": "selection",
"select": {
"type": "interval"
}
}
]
}
Vega-Lite conditions are like if-statements.
Two ways to use them:
condition
argument in an encoding (see above)
condition versions of encoding channels (see below)
[1] "vl_condition_angle" "vl_condition_color"
[3] "vl_condition_description" "vl_condition_fill"
[5] "vl_condition_fillOpacity" "vl_condition_href"
[7] "vl_condition_opacity" "vl_condition_order"
[9] "vl_condition_shape" "vl_condition_size"
[11] "vl_condition_stroke" "vl_condition_strokeDash"
[13] "vl_condition_strokeOpacity" "vl_condition_strokeWidth"
[15] "vl_condition_text" "vl_condition_tooltip"
[17] "vl_condition_url"
What elements do we need to create this interaction?
# create invisible points b/c nearest selecting
# only works with points, not with lines
points <- base |>
vl_mark_point(opacity = 0) |>
vl_encode_y("price:Q") |>
# create selection parameter
vl_add_point_selection(
"hilite", on = "pointermove",
nearest = TRUE, encodings = list("x"))
# draw a rule only for selected date
# empty = FALSE gives empty selection when nothing has been selected
rule <- base |>
vl_mark_rule(color = "black") |>
vl_filter(list(param = "hilite", empty = FALSE))
# less efficient: draw all the text, but most of it is invisible
# but it demonstrates how to use an encoding condition
text <- base |>
vl_mark_text(align = "right", dx = -6, dy = 8) |>
vl_encode_text("date:T") |>
vl_encode_y(value = 1) |>
vl_encode_color(value = "black") |>
vl_encode_opacity(value = 0.0) |>
vl_condition_opacity(param = "hilite", value = 1, empty = FALSE)
lines + points + rule + text
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"layer": [
{
"layer": [
{
"data": {
"url": "https://cdn.jsdelivr.net/npm/vega-datasets@v1.29.0/data/stocks.csv"
},
"encoding": {
"x": {
"field": "date",
"type": "temporal"
},
"y": {
"field": "price",
"type": "quantitative"
},
"color": {
"field": "symbol",
"type": "nominal"
}
},
"height": 200,
"width": 500,
"mark": {
"type": "line"
}
},
{
"data": {
"url": "https://cdn.jsdelivr.net/npm/vega-datasets@v1.29.0/data/stocks.csv"
},
"encoding": {
"x": {
"field": "date",
"type": "temporal"
},
"y": {
"field": "price",
"type": "quantitative"
}
},
"height": 200,
"width": 500,
"mark": {
"opacity": 0,
"type": "point"
},
"params": [
{
"name": "hilite",
"select": {
"encodings": [
"x"
],
"nearest": true,
"on": "pointermove",
"type": "point"
}
}
]
}
]
},
{
"data": {
"url": "https://cdn.jsdelivr.net/npm/vega-datasets@v1.29.0/data/stocks.csv"
},
"encoding": {
"x": {
"field": "date",
"type": "temporal"
}
},
"height": 200,
"width": 500,
"mark": {
"color": "black",
"type": "rule"
},
"transform": [
{
"filter": {
"param": "hilite",
"empty": false
}
}
]
}
]
}
penguins_scatter |>
vl_add_interval_selection(
name = "panzoom",
# bind the interval selection to x and y the scales
bind = "scales", encodings = c("x", "y"),
# pan/zoom affects all panels (the default in this situation)
# other options are "intersect" and "union"
resolve = "global", # each panel affects all panels (default)
translate = TRUE, # enable panning (default)
zoom = TRUE) # enable zooming (default)
detail <- vl_chart(width = 480) |>
vl_mark_area() |>
vl_encode_x('date:T') |>
vl_axis_x(title = '') |>
vl_encode_y('price:Q')
overview <- vl_chart(width = 480, height = 60) |>
vl_mark_area() |>
vl_encode_x('date:T') |>
vl_encode_y('price:Q') |>
vl_axis_y(tickCount = 3, grid = FALSE)
vl_vconcat(detail, overview) |>
vl_add_data(url = "https://vega.github.io/vega-editor/app/data/sp500.csv")
vl_vconcat(
detail |>
# use selected x range to reset the domain
vl_scale_x(domain = list(param = 'brush')),
overview |>
# select a arange of x values (date) by brushing
vl_add_interval_selection(name = 'brush', encodings = list('x'))
) |>
vl_add_data(url = "https://vega.github.io/vega-editor/app/data/sp500.csv")
Splom = scatter plot matrix
splom <-
vl_chart(width = 150, height = 150) |>
vl_add_data(url = "https://vega.github.io/vega-editor/app/data/cars.json") |>
vl_mark_point() |>
vl_encode_x(field = list("repeat" = "column"), type = "quantitative") |>
vl_encode_y(field = list("repeat" = "row"), type = "quantitative") |>
vl_repeat_row("Horsepower", "Acceleration", "Miles_per_Gallon") |>
vl_repeat_col("Miles_per_Gallon", "Acceleration", "Horsepower")
splom
splom |>
# select with a brush -- selection affects all panels
vl_add_interval_selection("brush", resolve = "global") |>
# default (non-selected) color of dots is gray
vl_encode_color(value = "grey") |>
# if selected, color them according to the origin field
vl_condition_color(param = "brush", field = "Origin", type = "nominal")
tibble(x = 10^(seq(-4, 4, by = 0.25))) |>
vl_chart() |>
vl_mark_line() |>
vl_encode(x = "x:Q", y = "y:Q") |>
vl_scale_x(type = "symlog", constant = 100) |>
vl_scale_y(type = "symlog", constant = 100) |>
vl_add_parameter("slope", value = 55) |>
vl_add_parameter("intercept", value = 0) |>
vl_calculate("intercept + slope * datum.x", as = "y") |>
vl_bind_range_input("slope", min = 0, max = 100, step = 1) |>
vl_bind_range_input("intercept", min = 0, max = 100, step = 1)