Reputation: 3557
I have a plot with a linetype that are pill shaped. But I would like to draw them as circles. Is there a way to change the linetype in ggplot2 to get 1. circles, and 2. change the spacing between these circles (with a numeric parameter that would allow for more or less space between the circles)?
library(tidyverse)
x = factor(1:100)
y = 1
# set.seed(42)
df = data.frame(x, y)
add_lines = purrr::map(.x = 0:10, ~ df |>
mutate(y = y+.x+ sqrt(runif(1, min = 0, max = 20)),
gr = paste0('line', .x))) |>
bind_rows() |>
mutate(x_nb = as.numeric(x))
ggplot(data = add_lines,
mapping = aes(x = x,
y = sqrt(x_nb)*sin(y+pi*(x_nb/max(x_nb)))+cos(y)+sqrt(y)*-sin(sqrt(x_nb)),
group = gr,
color = gr)) +
geom_path(size = 2, linetype = '11',lineend = "round") +
scale_color_viridis_d() +
theme(panel.grid.major = element_line(linetype = "blank"),
panel.grid.minor = element_line(linetype = "blank"),
axis.title = element_text(size = 0),
axis.text = element_text(size = 0), axis.text.x = element_text(size = 0),
axis.text.y = element_text(size = 0),
plot.title = element_text(size = 0),
panel.background = element_rect(fill = "grey90"),
plot.background = element_rect(colour = NA),
axis.line = element_line(colour = NA),
axis.ticks = element_line(colour = NA),
legend.position = "none") +labs(x = NULL, y = NULL)
Upvotes: 0
Views: 41
Reputation: 174458
One way to tackle this is simply to draw dots along your paths using geom_point
. For this, we can write a helper function that takes your data frame and modifies it so that it gives equally-spaced points along each path using interpolation.
make_points <- function(data, x, y, groups = 1, spacing = 1) {
xvals <- data[[deparse(substitute(x))]]
yvals <- data[[deparse(substitute(y))]]
ratio <- diff(range(yvals)) / diff(range(xvals))
data %>%
group_by({{groups}}) %>%
mutate(dist = c(0, cumsum(sqrt(diff({{x}})^2 +
(diff({{y}}) / ratio)^2)))) |>
reframe(x = approx(dist, {{x}}, xout = seq(0, max(dist), spacing))$y,
y = approx(dist, {{y}}, xout = seq(0, max(dist), spacing))$y)
}
Personally I would move the trig calculations of the y values outside of ggplot. This allows you to focus on the data and plotting of the data individually. Note your theme code can be shortened a lot using theme_void
library(tidyverse)
set.seed(42)
add_lines <- purrr::map(.x = 0:10, function(.x) {
data.frame(x = 1:100, y = 1) |>
mutate(y = y+.x+ sqrt(runif(1, min = 0, max = 20)),
gr = paste0('line', .x),
y = sqrt(x)*sin(y+pi*(x/max(x)))+cos(y)+sqrt(y)*-sin(sqrt(x)))
}) |>
bind_rows()
ggplot(data = make_points(add_lines, x, y, gr, spacing = 2),
mapping = aes(x = x, y = y, group = gr, color = gr)) +
geom_point(size = 2) +
scale_color_viridis_d(guide = "none") +
theme_void() +
theme(panel.background = element_rect(fill = "grey90"))
Just adjust spacing
in the call to make_points
to change the spacing and size
inside geom_point
to control the circle size. For example, changing spacing
to 1.5 gives us
Upvotes: 1