gganimate for random walk model - r

I have created a random walk plot using ggplot2 (code below). I wondered if it would be possible to use the gganimate package so that the random walk process (the black line in the plot) gradually appears but stops once it touches the grey horizontal dashed line.
set.seed(3344)
create_random_walk <- function(number=500){
data.frame(x = rnorm(number),
rown = c(1:500)) %>%
mutate(xt = cumsum(x))
}
randomwalkdata <- rbind(mutate(create_random_walk(), run = 1))
p <- ggplot(randomwalkdata, aes(x = rown, y = xt)) +
geom_line() +
labs(x = '\nTime (arbitrary value)', y = 'Evidence accumulation\n') +
theme_classic()
p + geom_segment(aes(x = 0.5, xend = 500, y = 25, yend = 25, linetype = 2), colour = "grey", size = 1, show.legend = FALSE) +
scale_linetype_identity()
Can anybody help?

library(gganimate); library(dplyr)
animate(
ggplot(randomwalkdata |> filter(cumsum(lag(xt, default = 0) >= 25) == 0),
aes(x = rown, y = xt)) +
geom_line() +
geom_point(data = . %>% filter(rown == max(rown)),
size = 10, shape = 21, color = "red", stroke = 2) +
labs(x = '\nTime (arbitrary value)', y = 'Evidence accumulation\n') +
theme_classic() +
annotate("segment", x = 0.5, xend = 500, y = 25, yend = 25, linetype = 2,
colour = "grey", linewidth = 1) +
scale_linetype_identity() +
transition_reveal(rown),
end_pause = 20, width = 600)

Related

Create a special Radial bar chart (race track plot)

I was able to replicate another good answers here to create a basic radial plot, but can anyone give me any clue of others functions/parameters/ideas on how to convert the basic one to something similar to this :
You could get pretty close like this:
df <- data.frame(x = c(10, 12.5, 15), y = c(1:3),
col = c("#fcfbfc", "#fbc3a0", "#ec6f4a"))
library(ggplot2)
ggplot(df, aes(x = 0, xend = x, y = y, yend = y, color = col)) +
geom_hline(yintercept = c(1:3), size = 14, color = "#dfdfdf") +
geom_hline(yintercept = c(1:3), size = 13, color = "#f7f7f7") +
geom_segment(color = "#bf2c23", size = 14, lineend = 'round') +
geom_segment(size = 13, lineend = 'round') +
scale_color_identity() +
geom_point(aes(x = x - 0.03 * y), size = 5, color = "#bf2c23",
shape = 21, fill = 'white') +
geom_point(aes(x = x - 0.03 * y), size = 2, color = "#bf2c23",
shape = 21, fill = 'white') +
scale_y_continuous(limits = c(0, 4)) +
scale_x_continuous(limits = c(0, 20)) +
coord_polar() +
theme_void()
Here's a start. Are there particular aspects you're trying to replicate? This is a fairly customized format.
df <- data.frame(type = c("on", "ia", "n"),
radius = c(2,3,4),
value = c(10,21,22))
library(ggplot2); library(ggforce)
ggplot(df) +
geom_link(aes(x = radius, xend = radius,
y = 0, yend = value),
size = 17, lineend = "round", color = "#bb353c") +
geom_link(aes(x = radius, xend = radius,
y = 0, yend = value, color = type),
size = 16, lineend = "round") +
geom_label(aes(radius, y = 30,
label = paste(type, ": ", value)), hjust = 1.8) +
scale_x_continuous(limits = c(0,4)) +
scale_y_continuous(limits = c(0, 30)) +
scale_color_manual(values = c("on" = "#fff7f2",
"ia" = "#f8b68f",
"n" = "#e4593a")) +
guides(color = "none") +
coord_polar(theta = "y") +
theme_void()

Rstudio Bland Altman grouped colours and shapes

I have a bland-altman plot of 16 measurements divided over 3 groups (Slice) which I want to colorcode and possibly have different shapes but somehow I cant get it working:
df <- data.frame("Slice" = c(1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3),
"Segments" = c(1:16),
"mean" = c(6,5,2,4,8,9,6,3,5,6,5,8,5,4,6,4),
"dif" = c(1,3,2,1,2,3,2,1,2,2,2,1,3,2,1,2))
#creat limits of agreement
LL = mean(df$dif)-1.96*(sd(df$dif))
UL = mean(df$dif)+1.96*(sd(df$dif))
#create BA plot
BAplot <- ggplot(df, aes(x=mean,y=dif))+
geom_jitter(alpha=1.0,size=18,shape="*", stroke = 1.5)+
geom_hline(yintercept=mean(df$dif),color= "blue",size=2)+
geom_text(aes(x = 12, y = mean(df$dif)+0.2, label = round(mean(df$dif), 1)), col = "blue", size = 7) +
geom_hline(yintercept=0,linetype=3,size=2) +
geom_hline(yintercept=c(UL,LL),color="black",linetype="dashed",size=2)+theme_bw()+
geom_text(aes(x = 12, y = UL+0.2, label = round(UL,1)), col = "black", size = 7) +
geom_text(aes(x = 12, y = LL+0.2, label = round(LL,1)), col = "black", size = 7) +
scale_x_continuous("mean",limits = c(-2,12))+
scale_y_continuous("diff", limits = c(-1, 5.5))
To code your points by color and to have different shapes you have to map your Slice column on the color and/or shape aesthetic inside geom_jitter. As Slice is a numeric I first converted it to a factor. If you want specific colors or shape you could set your desired values using scale_color_manual and scale_shape_manual:
library(ggplot2)
ggplot(df, aes(x = mean, y = dif)) +
geom_jitter(aes(color = factor(Slice), shape = factor(Slice)), alpha = 1.0, size = 2) +
geom_hline(yintercept = mean(df$dif), color = "blue", size = 2) +
geom_text(aes(x = 12, y = mean(dif) + 0.2, label = round(mean(dif), 1)), col = "blue", size = 7) +
geom_hline(yintercept = 0, linetype = 3, size = 2) +
geom_hline(yintercept = c(UL, LL), color = "black", linetype = "dashed", size = 2) +
theme_bw() +
geom_text(aes(x = 12, y = UL + 0.2, label = round(UL, 1)), col = "black", size = 7) +
geom_text(aes(x = 12, y = LL + 0.2, label = round(LL, 1)), col = "black", size = 7) +
scale_x_continuous("mean", limits = c(-2, 12)) +
scale_y_continuous("diff", limits = c(-1, 5.5))

How to arrange data visualization in geom_segment() in a decreasing order?

I was trying to plot tweets' sources/devices in a decreasing order using ggplot/geom_segment in R.
Here is the code I ran:
ggplot(data = device, mapping = aes(x = fct_reorder(as.factor(source), n), y = n)) +
geom_segment(aes(x = source, xend = source, y = 0, yend = n)) +
theme(axis.text.x = element_text(angle = 90, hjust = 1, family = "sans")) +
labs(title = "Tweets by device/source", x = "device/source", y = "frequency") +
geom_point(size = 4, color = "red", fill = alpha("yellow", 0.3), alpha = 0.7, shape = 21, stroke = 2)
Here is the plot it returned, which is not in decreasing pattern as I wanted to be.
So, I was wondering how could I plot the geom_segment in decreasing order?
You used the correct approach, but at the wrong spot. Try to do the factor rearrangement on your data before the ggplot call. In your case you did the reordering, but then used the original "source" data and not the reordered one in geom_segment. Doing the reordering before the ggplot call fixes that.
Here is an example using the mtcars dataset:
mtcars %>%
rownames_to_column("model") %>%
as_tibble() %>%
mutate(model = fct_reorder(model, -mpg)) %>%
ggplot() +
geom_segment(aes(x = model, xend = model, y = 0, yend = mpg)) +
theme(axis.text.x = element_text(angle = 90, hjust = 1, family = "sans")) +
labs(title = "Tweets by device/source", x = "device/source", y = "frequency") +
geom_point(aes(x = model, y = mpg), size = 4, color = "red", fill = alpha("yellow", 0.3), alpha = 0.7, shape = 21, stroke = 2)
The new plot looks like this:
The improved code:
device %>%
as_tibble() %>%
mutate(source = fct_reorder(source, -n)) %>%
ggplot() +
geom_segment(aes(x = source, xend = source, y = 0, yend = n)) +
theme(axis.text.x = element_text(angle = 90, hjust = 1, family = "sans", size = 10)) +
labs(title = "Tweets by device/source", x = "device/source", y = "frequency") +
geom_point(aes(x = source, y = n), size = 3, color = "red", fill =
alpha("yellow", 0.3), alpha = 0.7, shape = 21, stroke = 2)

How to add a vertical blank space between straight and inverted geom_density() with ggplot2

I am trying to reproduce this kind of Figure, with two densities, a first one pointing upwards and a second one pointing downwards. I would also like to have some blank space between the two densities.
Here is the code I am currently using.
library(hrbrthemes)
library(tidyverse)
library(RWiener)
# generating data
df <- rwiener(n = 1e2, alpha = 2, tau = 0.3, beta = 0.5, delta = 0.5)
df %>%
ggplot(aes(x = q) ) +
geom_density(
data = . %>% filter(resp == "upper"),
aes(y = ..density..),
colour = "steelblue", fill = "steelblue",
outline.type = "upper", alpha = 0.8, adjust = 1, trim = TRUE
) +
geom_density(
data = . %>% filter(resp == "lower"),
aes(y = -..density..), colour = "orangered", fill = "orangered",
outline.type = "upper", alpha = 0.8, adjust = 1, trim = TRUE
) +
# stimulus onset
geom_vline(xintercept = 0, lty = 1, col = "grey") +
annotate(
geom = "text",
x = 0, y = 0,
# hjust = 0,
vjust = -1,
size = 3, angle = 90,
label = "stimulus onset"
) +
# aesthetics
theme_ipsum_rc(base_size = 12) +
theme(axis.text.y = element_blank() ) +
labs(x = "Reaction time (in seconds)", y = "") +
xlim(0, NA)
Which results in something like...
How could I add some vertical space between the two densities to reproduce the above Figure?
If you want to try without faceting, you're probably best to just plot the densities as polygons with adjusted y values according to your desired spacing:
s <- 0.25 # set to change size of the space
ud <- density(df$q[df$resp == "upper"])
ld <- density(df$q[df$resp == "lower"])
x <- c(ud$x[1], ud$x, ud$x[length(ud$x)],
ld$x[1], ld$x, ld$x[length(ld$x)])
y <- c(s, ud$y + s, s, -s, -ld$y - s, -s)
df2 <- data.frame(x = x, y = y,
resp = rep(c("upper", "lower"), each = length(ud$x) + 2))
df2 %>%
ggplot(aes(x = x, y = y, fill = resp, color = resp) ) +
geom_polygon(alpha = 0.8) +
scale_fill_manual(values = c("steelblue", "orangered")) +
scale_color_manual(values = c("steelblue", "orangered"), guide = guide_none()) +
geom_vline(xintercept = 0, lty = 1, col = "grey") +
annotate(
geom = "text",
x = 0, y = 0,
# hjust = 0,
vjust = -1,
size = 3, angle = 90,
label = "stimulus onset"
) +
# aesthetics
theme_ipsum_rc(base_size = 12) +
theme(axis.text.y = element_blank() ) +
labs(x = "Reaction time (in seconds)", y = "")
you can try facetting
set.seed(123)
q=rbeta(100, 0.25, 1)
df_dens =data.frame(gr=1,
x=density(df$q)$x,
y=density(df$q)$y)
df_dens <- rbind(df_dens,
data.frame(gr=2,
x=density(df$q)$x,
y=-density(df$q)$y))
ggplot(df_dens, aes(x, y, fill = factor(gr))) +
scale_x_continuous(limits = c(0,1)) +
geom_area(show.legend = F) +
facet_wrap(~gr, nrow = 2, scales = "free_y") +
theme_minimal() +
theme(strip.background = element_blank(),
strip.text.x = element_blank(),
axis.text.y = element_blank(),
axis.title.y = element_blank())
The space between both plots can be increased using panel.spacing = unit(20, "mm"). Instead of facet_grid you can also try facet_grid(gr~., scales = "free_y")

Drawing elements (arrows & circle) in ggplot (R) to show the difference between two bars

I am trying to create a plot in R using ggplot that shows the difference between my two bars in a nice way.
I found an example that did part of what I wanted, but I have two major problems:
It is based on comparing groups of bars, but I only have two, so I added one group with both of them.
I would like to draw the arrow in nicer shape. I attached an image.
Code:
transactions <- c(5000000, 1000000)
time <- c("Q1","Q2")
group <- c("A", "A")
data <- data.frame(transactions, time, group)
library(ggplot2)
fun.data <- function(x){
print(x)
return(data.frame(y = max(x) + 1,
label = paste0(round(diff(x), 2), "cm")))
}
ylab <- c(2.5, 5.0, 7.5, 10)
gg <- ggplot(data, aes(x = time, y = transactions, fill = colors_hc[1], label = round(transactions, 0))) +
geom_bar(stat = "identity", show.legend = FALSE) +
geom_text(position = position_dodge(width = 0.9),
vjust = 1.1) +
geom_line(aes(group = group), position = position_nudge(0.1),
arrow = arrow()) +
stat_summary(aes(x = group, y = transactions),
geom = "label",
fun.data = fun.data,
fontface = "bold", fill = "lightgrey",
inherit.aes = FALSE) +
expand_limits(x = c(0, NA), y = c(0, NA)) +
scale_y_continuous(labels = paste0(ylab, "M"),
breaks = 10 ^ 6 * ylab)
gg
The arrows I am aiming for:
Where I am (ignore the ugliness, didn't style it yet):
This works, but you still need to play around a bit with the axes (or rather beautify them)
library(dplyr)
library(ggplot2)
transactions <- c(5000000, 1000000)
time <- c("Q1","Q2")
group <- c("A", "A")
my_data <- data.frame(transactions, time, group)
fun.data <- function(x){
return(data.frame(y = max(x) + 1,
label = as.integer(diff(x))))
}
my_data %>%
ggplot(aes(x = group, y = transactions, fill = time)) +
geom_bar(stat = 'identity', position = 'dodge') +
geom_text(aes(label = as.integer(transactions)),
position = position_dodge(width = 0.9),
vjust = 1.5) +
geom_line(aes(group = group), position = position_nudge(0.1),
arrow = arrow()) +
stat_summary(aes(x = group, y = transactions),
geom = "label",
size = 5,
position = position_nudge(0.05),
fun.data = fun.data,
fontface = "bold", fill = "lightgrey",
inherit.aes = FALSE)
Edit2:
y_limit <- 6000000
my_data %>%
ggplot(aes(x = time, y = transactions)) +
geom_bar(stat = 'identity',
fill = 'steelblue') +
geom_text(aes(label = as.integer(transactions)),
vjust = 2) +
coord_cartesian(ylim = c(0, y_limit)) +
geom_segment(aes(x = 'Q1', y = max(my_data$transactions),
xend = 'Q1', yend = y_limit)) +
geom_segment(aes(x = 'Q2', y = y_limit,
xend = 'Q2', yend = min(my_data$transactions)),
arrow = arrow()) +
geom_segment(aes(x = 'Q1', y = y_limit,
xend = 'Q2', yend = y_limit)) +
geom_label(aes(x = 'Q2',
y = y_limit,
label = as.integer(min(my_data$transactions)- max(my_data$transactions))),
size = 10,
position = position_nudge(-0.5),
fontface = "bold", fill = "lightgrey")

Resources