My question is if there is a way to create two graphs that move one point up or down at a time in a random walk, and there will be a high [synthetic] correlation between them [example: 0.8 in Pearson's correlation]
Thank you
My question is if there is a way to create two graphs that move one point up or down at a time in a random walk, and there will be a high [synthetic] correlation between them [example: 0.8 in Pearson's correlation]
Thank you
As whuber notes in the comments, a version of this can be done using correlated Bernoulli random variables. It is possible to generate correlated Bernoulli random variables and form random walks from this, but the resulting correlation of the larger increments of the random walks are more complicated.
In any case, here is a function you can use to generate correlated Bernoulli random variables (this is taken from my answer to this related question).
rcorrbinom <- function(n, size = 1, prob1, prob2, corr = 0) {
#Check inputs
if (!is.numeric(n)) { stop('Error: n must be numeric') }
if (length(n) != 1) { stop('Error: n must be a single number') }
if (as.integer(n) != n) { stop('Error: n must be a positive integer') }
if (n < 1) { stop('Error: n must be a positive integer') }
if (!is.numeric(size)) { stop('Error: n must be numeric') }
if (length(size) != 1) { stop('Error: n must be a single number') }
if (as.integer(size) != size) { stop('Error: n must be a positive integer') }
if (size < 1) { stop('Error: n must be a positive integer') }
if (!is.numeric(prob1)) { stop('Error: prob1 must be numeric') }
if (length(prob1) != 1) { stop('Error: prob1 must be a single number') }
if (prob1 < 0) { stop('Error: prob1 must be between 0 and 1') }
if (prob1 > 1) { stop('Error: prob1 must be between 0 and 1') }
if (!is.numeric(prob2)) { stop('Error: prob2 must be numeric') }
if (length(prob2) != 1) { stop('Error: prob2 must be a single number') }
if (prob2 < 0) { stop('Error: prob2 must be between 0 and 1') }
if (prob2 > 1) { stop('Error: prob2 must be between 0 and 1') }
if (!is.numeric(corr)) { stop('Error: corr must be numeric') }
if (length(corr) != 1) { stop('Error: corr must be a single number') }
if (corr < -1) { stop('Error: corr must be between -1 and 1') }
if (corr > 1) { stop('Error: corr must be between -1 and 1') }
#Compute probabilities
P00 <- (1-prob1)*(1-prob2) + corr*sqrt(prob1*prob2*(1-prob1)*(1-prob2));
P01 <- 1 - prob1 - P00;
P10 <- 1 - prob2 - P00;
P11 <- P00 + prob1 + prob2 - 1;
PROBS <- c(P00, P01, P10, P11)
if (min(PROBS) < 0) { stop('Error: corr is not in the allowable range') }
#Generate the output
RAND <- array(sample.int(4, size = n*size, replace = TRUE, prob = PROBS),
dim = c(n, size));
VALS <- array(0, dim = c(2, n, size));
OUT <- array(0, dim = c(2, n));
for (i in 1:n) {
for (j in 1:size) {
VALS[1,i,j] <- (RAND[i,j] %in% c(3, 4));
VALS[2,i,j] <- (RAND[i,j] %in% c(2, 4)); }
OUT[1, i] <- sum(VALS[1,i,]);
OUT[2, i] <- sum(VALS[2,i,]); }
#Give output
OUT; }
You can use this to generate two correlated random walks. In the code below I generate correlated random walks $\{ (X_t,Y_t) | t \in \mathbb{R} \}$ using the anchoring point $X_0=Y_0 = 0$ and the correlation value $\rho = 0.4$.
#Set parameters
n <- 1000
CORR <- 0.4;
#Generate correlated random walks
SAMPLE <- rcorrbinom(n = n, prob1 = 0.5, prob2 = 0.5, corr = CORR);
WALK1 <- -(1:n) + 2*cumsum(SAMPLE[1,]);
WALK2 <- -(1:n) + 2*cumsum(SAMPLE[2,]);
WALKS <- data.frame(Time = 1:n, Walk1 = WALK1, Walk2 = WALK2);
#Plot the random walks
library(ggplot2);
THEME <- theme(plot.title = element_text(hjust = 0.5, size = 14, face = 'bold'),
plot.subtitle = element_text(hjust = 0.5, face = 'bold'));
FIGURE <- ggplot(aes(x = Time), data = WALKS) +
geom_line(aes(y = Walk1), colour = 'Red') +
geom_line(aes(y = Walk2), colour = 'Blue') +
THEME +
ggtitle('Correlated Random Walks') + ylab('Value');