Reputation: 106
I have something of a basic question as I do some preliminary coding in preparation for my dissertation. I have some experience with R, but am still somewhat new. I've looked all over the internet, and haven't found a good answer yet. Hope someone out there can help improve my code and make it more efficient.
I'm trying to create a series of 4 randomly-drawn 5x5 networks that change slightly at each time point. To do that, I create a vector of 25 randomly drawn (prob=.5) 0s and 1s, and then create a 5x5 matrix from the vector. The matrix will serve as the adjacency matrix for each network. Creating the initial matrix is pretty easy:
a <- rbinom(25, 1, .5)
matrix_a <- matrix(a, ncol = 5, nrow = 5)
This matrix will serve as my network at time point 1. For time points 2-4, I want 5 randomly-selected cells to flip, so a 0 becomes a 1, and a 1 becomes a 0. For those unfamiliar with networks, that means in five instances edges change and are added (if there wasn't one before) or are removed (if there was).
The way I've figured out how to do that is to first select 5 elements from the vector b at random:
spot <- sample(25,5)
This will give me a vector of 5 elements representing a randomly-drawn position from 1 to 25. Next, I want to change those 5 zeroes or ones to their opposite (so a zero becomes a one and vice versa), and then I can insert them back into the 25-vector element, and make matrix_b at time point 2 from that, and repeat two more times. This way, the networks stay fairly stable, but change slightly and at random at time points 2 through 4.
But here's where I'm having trouble. I'd like to create a function to automate changing the five zeroes to ones and vice versa, which seems like it should be easy to do. So far, this is the best I've been able to pull off:
x <- (a[spot])
y1 <- if (x[1]==0) {
x[1]+1
} else {
x[1]-1
}
y1
y2 <- if (x[2]==0) {
x[2]+1
} else {
x[2]-1
}
y2
I've tested this, and it does change a zero to a one and vice versa.
I repeat that three more times to create y3, y4, and y5, then create a new vector of 5 elements:
y <- c(y1,y2,y3,y4,y5)
y
Now I replace five elements from the 25-element vector a with the vector y above (which have changed from zeroes to ones and vice versa) to create the new vector b:
b <- a
b[spot] <- y
matrix_b <- matrix(b, ncol = 5, nrow = 5)
I wind up with matrix_b at time point 2, in which with 5 cells have changed from zero to one or vice versa representing edges that have been added or dropped.
This will work, but it's really inefficient. I know there's a way to automate--using functions? apply?--creating y1 through y5 above. But I've been looking for hours, and this is still the best I can do.
Any suggestions for improving the code? Thanks in advance for any help you're able to offer.
Upvotes: 1
Views: 535
Reputation: 37641
You can change all of the sampled values at once with b[spot] = 1 - b[spot]
Upvotes: 1