library(gglite)
gglite can automatically infer the mark type from your data and aesthetic
mappings in many cases — for example, numeric × numeric data defaults to
mark_point(), and categorical × unique numeric data defaults to
mark_interval(). This means you can often omit the mark_*() call
entirely. All marks are specified explicitly on this page because the purpose
here is to document each mark type individually.
g2(mtcars, hp ~ mpg) |> mark_point()
g2(mtcars, hp ~ mpg, color = ~ wt) |>
mark_point()
g2(mtcars, hp ~ mpg, size = ~ wt) |> mark_point()
g2(iris, Sepal.Length ~ Sepal.Width, shape = ~ Species) |>
mark_point()
g2(mtcars, hp ~ mpg, size = 10) |>
mark_point() |>
style_mark(fill = 'lightyellow', stroke = 'steelblue', lineWidth = 2)
df = data.frame(x = 1:10, y = cumsum(rnorm(10)))
g2(df, y ~ x) |> mark_line()
df = data.frame(
x = rep(1:5, 2), y = c(3, 1, 4, 1, 5, 2, 7, 1, 8, 3),
group = rep(c('A', 'B'), each = 5)
)
g2(df, y ~ x, color = ~ group) |> mark_line()
df = data.frame(x = c('A', 'B', 'C', 'D'), y = c(3, 7, 2, 5))
g2(df, y ~ x) |> mark_interval()
df = data.frame(
x = rep(c('A', 'B', 'C'), each = 2), y = c(3, 2, 5, 4, 1, 6),
color = rep(c('a', 'b'), 3)
)
g2(df, y ~ x, color = ~ color) |>
mark_interval() |> transform('stackY')
g2(df, y ~ x, color = ~ color) |>
mark_interval() |> transform('dodgeX')
df = data.frame(x = 1:10, y = c(3, 1, 4, 1, 5, 9, 2, 6, 5, 3))
g2(df, y ~ x) |> mark_area()
df = data.frame(
x = rep(1:5, 2), y = c(3, 1, 4, 1, 5, 2, 7, 1, 8, 3),
group = rep(c('A', 'B'), each = 5)
)
g2(df, y ~ x, color = ~ group) |>
mark_area() |> transform('stackY')
g2(mtcars, hp ~ mpg) |>
mark_rect() |>
transform('bin', thresholdsX = 10, thresholdsY = 10)
df = expand.grid(x = LETTERS[1:5], y = LETTERS[1:5])
df$value = seq_len(nrow(df))
g2(df, y ~ x, color = ~ value) |> mark_cell()
df = data.frame(x = c('A', 'B', 'C'), y = c(3, 7, 2))
g2(df, y ~ x) |>
mark_interval() |>
mark_text(encode = list(text = 'y'))
The path mark in G2 uses an SVG-like d channel to draw arbitrary
shapes. It does not use x/y data coordinates like mark_line(). Use
mark_line() to connect data points in order.
g2(df, y ~ x) |> mark_path()
A line mark connecting data points in order:
n = 100
t = seq(0, 4 * pi, length.out = n)
df = data.frame(x = t * cos(t), y = t * sin(t))
g2(df, y ~ x) |> mark_line()
The polygon mark draws filled polygons. Use list columns to store
vertex coordinates for each polygon.
df = data.frame(group = c('triangle', 'square'))
df$x = list(c(0, 1, 0.5), c(2, 3, 3, 2))
df$y = list(c(0, 0, 1), c(0, 0, 1, 1))
g2(df, color = ~ group) |>
mark_polygon(encode = list(x = 'x', y = 'y'))
df = data.frame(
x = c('A', 'B', 'C'), y = c(1, 3, 2),
x1 = c('B', 'C', 'D'), y1 = c(3, 1, 4)
)
g2(df) |>
mark_link(encode = list(x = c('x', 'x1'), y = c('y', 'y1'))) |>
style_mark(stroke = 'steelblue', lineWidth = 2)
g2(mtcars, hp ~ mpg) |>
mark_point() |>
mark_line_x(
data = list(list(x = mean(mtcars$mpg))),
encode = list(x = 'x')
) |>
style_mark(stroke = 'red', lineDash = c(4, 4))
g2(mtcars, hp ~ mpg) |>
mark_point() |>
mark_line_y(
data = list(list(y = mean(mtcars$hp))),
encode = list(y = 'y')
) |>
style_mark(stroke = 'red', lineDash = c(4, 4))
g2(mtcars, hp ~ mpg) |>
mark_point() |>
mark_range(
data = list(list(x = c(15, 25), y = c(100, 200))),
encode = list(x = 'x', y = 'y')
) |>
style_mark(fill = 'steelblue', fillOpacity = 0.15)
g2(mtcars, hp ~ mpg) |>
mark_point() |>
mark_range_x(
data = list(list(x = c(15, 25))),
encode = list(x = 'x')
) |>
style_mark(fill = 'steelblue', fillOpacity = 0.15)
g2(mtcars, hp ~ mpg) |>
mark_point() |>
mark_range_y(
data = list(list(y = c(100, 200))),
encode = list(y = 'y')
) |>
style_mark(fill = 'orange', fillOpacity = 0.15)
df = data.frame(x = c('A', 'B'), y = c(3, 7))
g2(df, y ~ x) |>
mark_interval() |>
mark_connector(
data = list(list(x = 'A', x1 = 'B')),
encode = list(x = 'x', x1 = 'x1')
) |>
labels(text = '+133%')
g2(iris, Sepal.Width ~ Species) |> mark_boxplot()
The beeswarm mark uses force simulation to arrange individual data points
without overlap, creating a beeswarm layout useful for visualizing distributions
within categories.
g2(iris, Sepal.Width ~ Species) |> mark_beeswarm()
g2(iris, Sepal.Width ~ Species, color = ~ Species) |>
mark_beeswarm()
g2(iris, Sepal.Width ~ Species) |>
mark_beeswarm() |> mark_boxplot() |> style_mark(boxFillOpacity = 0.15)
g2() |>
mark_liquid(data = list(value = 0.6)) |>
style_mark(contentText = '60%', contentFill = 'white', contentFontSize = 40)
g2(iris, Sepal.Length ~ Sepal.Width, color = ~ Petal.Length) |>
mark_heatmap()
The image mark places images at data coordinates.
df = data.frame(
x = c(1, 2, 3), y = c(3, 5, 2),
url = rep(
'https://cdn.jsdelivr.net/npm/@browser-logos/chrome/chrome_64x64.png', 3
)
)
g2(df, y ~ x) |>
mark_image(encode = list(src = 'url')) |>
style_mark(width = 30, height = 30)
df = data.frame(
text = c('Hello', 'Data', 'Science', 'R', 'G2', 'Chart', 'Vis', 'Stats'),
value = c(30, 25, 20, 18, 15, 12, 10, 8)
)
g2(df) |>
mark_word_cloud(
encode = list(text = 'text', value = 'value', color = 'text')
)
df = data.frame(
source = c('Coal', 'Coal', 'Oil', 'Oil', 'Gas', 'Gas', 'Solar'),
target = c('Electricity', 'Heat', 'Electricity', 'Transport',
'Electricity', 'Heat', 'Electricity'),
value = c(25, 10, 15, 20, 20, 5, 10)
)
g2(df) |>
mark_sankey(
encode = list(source = 'source', target = 'target', value = 'value'),
layout = list(nodeAlign = 'center', nodePadding = 0.03)
)
df = data.frame(
source = c('A', 'A', 'A', 'B', 'B', 'C'),
target = c('B', 'C', 'D', 'C', 'D', 'D'),
value = c(5, 3, 2, 4, 1, 3)
)
g2(df) |>
mark_chord(
encode = list(source = 'source', target = 'target', value = 'value')
)
tree_data = list(
name = 'root', children = list(
list(name = 'Frontend', children = list(
list(name = 'React', value = 180),
list(name = 'Vue', value = 120),
list(name = 'Angular', value = 80)
)),
list(name = 'Backend', children = list(
list(name = 'Node.js', value = 150),
list(name = 'Python', value = 130),
list(name = 'Go', value = 90)
)),
list(name = 'Data', children = list(
list(name = 'R', value = 100),
list(name = 'Julia', value = 40)
))
)
)
g2() |>
mark_treemap(
data = list(type = 'inline', value = tree_data),
encode = list(value = 'value')
)
g2() |>
mark_pack(
data = list(type = 'inline', value = tree_data),
encode = list(value = 'value', color = 'depth'),
legend = FALSE
) |>
style_mark(labelText = js(
'(d) => d.r >= 10 && d.height === 0 ? d.data.name : ""'
))
g2() |>
mark_gauge(
data = list(
type = 'inline',
value = list(target = 120, total = 400, name = 'score')
)
)
g2() |>
mark_force_graph(
data = list(type = 'inline', value = list(
nodes = list(
list(id = 'CEO'), list(id = 'CTO'), list(id = 'CFO'),
list(id = 'VP Eng'), list(id = 'VP Sales'),
list(id = 'Dev Lead'), list(id = 'Backend'),
list(id = 'Frontend'), list(id = 'Accounting'),
list(id = 'Payroll'), list(id = 'Sales Rep 1'),
list(id = 'Sales Rep 2')
),
links = list(
list(source = 'CEO', target = 'CTO'),
list(source = 'CEO', target = 'CFO'),
list(source = 'CEO', target = 'VP Sales'),
list(source = 'CTO', target = 'VP Eng'),
list(source = 'VP Eng', target = 'Dev Lead'),
list(source = 'Dev Lead', target = 'Backend'),
list(source = 'Dev Lead', target = 'Frontend'),
list(source = 'CFO', target = 'Accounting'),
list(source = 'CFO', target = 'Payroll'),
list(source = 'VP Sales', target = 'Sales Rep 1'),
list(source = 'VP Sales', target = 'Sales Rep 2'),
list(source = 'Backend', target = 'Frontend')
)
)),
nodeLabels = list(list(text = 'id'))
)
g2() |>
mark_tree(
data = list(type = 'inline', value = list(
name = 'Company', children = list(
list(name = 'Engineering', children = list(
list(name = 'Frontend'),
list(name = 'Backend'),
list(name = 'DevOps')
)),
list(name = 'Marketing', children = list(
list(name = 'SEO'),
list(name = 'Content')
)),
list(name = 'Finance', children = list(
list(name = 'Accounting'),
list(name = 'Payroll')
))
)
)),
nodeLabels = list(list(text = 'name'))
)
The density mark computes kernel density estimation (KDE) automatically
from the x aesthetic. Map color for grouped density curves.
g2(iris, ~ Sepal.Width, color = ~ Species) |> mark_density()
tree_data = list(
name = 'root', children = list(
list(name = 'Frontend', children = list(
list(name = 'React', value = 180),
list(name = 'Vue', value = 120),
list(name = 'Angular', value = 80)
)),
list(name = 'Backend', children = list(
list(name = 'Node.js', value = 150),
list(name = 'Python', value = 130),
list(name = 'Go', value = 90)
)),
list(name = 'Data', children = list(
list(name = 'R', value = 100),
list(name = 'Julia', value = 40)
))
)
)
g2() |>
mark_sunburst(
data = list(type = 'inline', value = list(tree_data)),
encode = list(value = 'value')
) |>
style_mark(inset = 0.5)