variable data in loop in R - r

I have the code below where I have a loop above which is fed with a single value X:
n = 25
X = 1
p = 0.2 #probability
P = matrix( c(p, 1-p, 0, 0, 0, 0,
p, 0, 1-p, 0, 0, 0,
p, 0, 0, 1-p, 0, 0,
0, p, 0, 0, 1-p, 0,
0, 0, p, 0, 0, 1-p,
0, 0, 0, p, 0, 1-p),
ncol=6, nrow=6, byrow = TRUE) #transition matrix
for(i in 1:n){
Y = runif(1) #uniform sample
k = P[X[i], ] #calculate k values
k = cumsum(k)
if(Y <= k[1]){ #update the chain
X[i+1] = 1}
else if(Y <= k[2]){
X[i+1] = 2}
else if (Y <= k[3]){
X[i+1] = 3}
else if (Y<=k[4]){
X[i+1] = 4}
else if (Y<=k[5]){
X[i+1] = 5}
else {X[i+1]=6}
}
plot(1:n, X[1:i], type = 's')
I'm wondering that can I set my X be multi data like X = c(1,3,4), such that I can run all three values for X in only one line of code without having to resimulate by changing the value for X? The three graphs should be produced as a result.

First of all, you will want to put your code inside a function, if you aim to re-use that code. Secondly, in the code you posted, you plot the graph in the graphic device, which will be lost after you plot something else, so you might wanna save it as a PDF or PNG or something like that:
xtoplot <- function(X, n = 25, p = 0.2, transit = P){
for(i in 1:n){
Y <- runif(1) # uniform sample
k <- P[X[i], ] # calculate k values
k <- cumsum(k)
if(Y <= k[1]){ # update the chain
X[i+1] <- 1}
else if(Y <= k[2]){
X[i+1] <- 2}
else if(Y <= k[3]){
X[i+1] <- 3}
else if(Y <= k[4]){
X[i+1] <- 4}
else if(Y <= k[5]){
X[i+1] <- 5}
else{
X[i+1] <- 6}
}
pltname <- paste0("plot_", X, ".pdf") # The document name of the plot
pdf(pltname) # Tell R to prepare to export something to PDF
plot(1:n, X[1:i], type = 's') # The plot to be exported
dev.off()
}
Now that the function is in place, you can use a member of the "apply()-family" to run the function for multiple input values for X like this:
lapply(c(1,3,4), xtoplot)
In your working directory, you will find three PDFs called plot_1.pdf, plot_3.pdf and plot_4.pdf with the graphs you were looking for.

Related

R function to plot inequalities with shading

Suppose I have a set of inequalities:
-2x + y <= -3
1.25x + y <= 2.5
y >= -3
And I can summarize the information as follows:
mat <- matrix(c(-2, 1, 1.25, 1, 0, 1), nrow = 3, byrow = TRUE)
dir <- c("<=", "<=", ">=")
rhs <- c(-3, 2.5, -3)
I wrote the following function to plot the inequalities:
plot(0, 0, xlim = c(-1, 5), ylim = c(-4, 1))
plot_ineq <- function(mat, dir, rhs, xlow, xhigh){
line <- list()
for(i in 1:nrow(mat)){
if(mat[i, 2] > 0){
line[[i]] <- sapply(seq(xlow, xhigh, 0.1), function(x) (rhs[i] - mat[i, 1] * x)/mat[i, 2])
}else if(mat[i, 2] < 0){
line[[i]] <- sapply(seq(xlow, xhigh, 0.1), function(x) (rhs[i] - mat[i, 1] * x)/mat[i, 2])
if(dir[i] == ">="){
dir[i] = "<="
}else dir[i] = ">="
}
lines(seq(xlow, xhigh, 0.1), line[[i]])
}
}
plot_ineq(mat = mat, dir = dir, rhs = rhs, xlow = -1, xhigh = 5)
I have two questions: (1) how can I have a blank plot without having the (0, 0) point there? and (2) how can I shade the corresponding region according to dir? Should I try ggplot2?
I'm simply looking to shade the area that is described by the set of inequalities above. Not where (0, 0) lies.
1) Change the last inequality to be the same direction as the others and then use plotPolytope in gMOIP.
library(gMOIP)
mat <- matrix(c(-2, 1, 1.25, 1, 0, -1), nrow = 3, byrow = TRUE)
rhs <- c(-3, 2.5, 3)
argsFaces <- list(argsGeom_polygon = list(fill = "blue"))
plotPolytope(mat, rhs, argsFaces = argsFaces)
giving (continued after image)
2) The above uses ggplot2 graphics but if you prefer classic graphics then using mat and rhs from above:
library(gMOIP)
cp <- cornerPoints(mat, rhs)
cp <- cp[chull(cp), ] # chull gives indices of convex hull in order
plot(cp, type = "n")
polygon(cp, col = "blue")
# not shown but to add lines run this too
for(i in 1:nrow(cp)) {
ix <- if (i < nrow(cp)) i + 0:1 else c(i, 1)
b <- diff(cp[ix, 2]) / (d <- diff(cp[ix, 1]))
if (abs(d) < 1e-5) abline(v = a <- cp[i, 1])
else abline(a = a <- cp[i, 2] - b * cp[i, 1], b = b)
}
giving (continued after image)
3) Note that there is an archived package named intpoint on CRAN and it could be used to draw the boundary of the feasible region and lines. It does have the limitation that it is hard coded to show X and Y axes between -1 and 5 although it might not be hard to generalize it. It is used like this (output not shown) where mat, rhs and cp are from above.
library(intpoint)
intpoint:::show2d(mat, rhs, c = numeric(2))
polygon(cp, col = "blue")

Mathematica Plotting Solve Results

Remove["Global`*"]
a = 0;
For[z = 0, z < 3, z++, Sol[a] = x /. Solve[z^2 + x == 10, x];
a = a + 1;]
I am new to the mathematica so I'm experimenting with it.Answer of the problem changes at every loop so I stored them inside an array.
I can see the numeric results using Do[Print[Sol[a]], {a, 0, 2}]; but how can I plot the results I tried using Plot[Sol[[a]], {a, 0, 2}] but it didn't work.
Remove["Global`*"]
func = z^2 + x == 10;
sol = Solve[func, x];
Plot[x /. sol, {z, 0, 3}]

Developing a Continuous-time Markov Chain model to simulate the distribution (counts) of parasites on a fish in R

I am developing a (complex) CTMC model in R (as a beginner in R) to simulate the distribution of parasite load (counts) at 8 different body parts of a fish; assuming a parasite can move from one body part to another randomly. To start with a simple block of codes as below, it is able to simulate CTMC but returns errors below when trying to repeat it a number of times (for some runs).
Error in sample.int(x, size, replace, prob) : too few positive
probabilities
Warning message:
In rexp(1, Qt) : NAs produced
I realized, most of the rate values in the Q (matrix) are zero and thus, sampling at such instances, returns such as error. I would like to know if there is anyway to correct this error so as to run the model a number of times without such an error.
To make it simple, I started with these piece of codes:
Fishsim_model <- function(b,d,m,X0,Ti){
#b=birth rate; d=death rate; m=movement rate; Ti=finishing time
#X0=initial distribution; X= states
X <- X0
Ti <- floor(Ti)
ti <- 0 # (initial) time
day <- 1
saved <- matrix(0, Ti+1, 8) #Matrix of zeros to save final results
saved[day,] <- X0
Q <- rep(0, 36) # vector of rates
Qt <- 0 # Qt = sum(Q) is departure rate from current state
while (ti < Ti){
#Calculate rates
Q[1]<-X[1]*b
Q[2]<-X[2]*b
Q[3]<-X[3]*b
Q[4]<-X[4]*b
Q[5]<-X[5]*b
Q[6]<-X[6]*b
Q[7]<-X[7]*b
Q[8]<-X[8]*b
Q[9]<-X[1]*d
Q[10]<-X[2]*d
Q[11]<-X[3]*d
Q[12]<-X[4]*d
Q[13]<-X[5]*d
Q[14]<-X[6]*d
Q[15]<-X[7]*d
Q[16]<-X[8]*d
Q[17]<-X[1]*m
Q[18]<-X[3]*m/3
Q[19]<-X[4]*m/5
Q[20]<-X[6]*m/2
Q[21]<-X[4]*m/5
Q[22]<-X[5]*m/2
Q[23]<-X[2]*m/2
Q[24]<-X[5]*m/2
Q[25]<-X[3]*m/2
Q[26]<-X[2]*m/2
Q[27]<-X[3]*m/3
Q[28]<-X[7]*m/2
Q[29]<-X[8]*m/2
Q[30]<-X[4]*m/5
Q[31]<-X[4]*m/4
Q[32]<-X[7]*m/2
Q[33]<-X[6]*m/2
Q[34]<-X[8]*m/2
Q[35]<-X[3]*m/4
Q[36]<-X[4]*m/5
Qt <- sum(Q)
# time for next jump
ti <- ti + rexp(1, Qt)
# new state
j <- sample(36, 1, prob = Q)
if (j == 1) {
X[1] <- X[1] + 1
} else if (j==2){
X[2]<- X[2]+1
} else if (j==3){
X[3]<-X[3]+1
} else if (j==4){
X[4]<-X[4]+1
} else if (j==5){
X[5]<-X[5]+1
} else if (j==6){
X[6]<-X[6]+1
} else if (j==7){
X[7]<-X[7]+1
} else if (j==8){
X[8]<-X[8]+1
} else if (j==9){
X[1]<-X[1]-1
} else if (j==10){
X[2]<-X[2]-1
} else if (j==11){
X[3]<-X[3]-1
} else if (j==12){
X[4]<-X[4]-1
} else if (j==13){
X[5]<-X[5]-1
} else if (j==14){
X[6]<-X[6]-1
} else if (j==15){
X[7]<-X[7]-1
}else if (j==16){
X[8]=X[8]-1
} else if (j==17){
X[1]=X[1]-1
X[3]=X[3]+1
} else if (j==18){
X[1]=X[1]+1
X[3]=X[3]-1
} else if (j==19){
X[4]=X[4]-1
X[6]=X[6]+1
} else if (j==20){
X[4]=X[4]+1
X[6]=X[6]-1
} else if (j==21){
X[4]=X[4]-1
X[5]=X[5]+1
} else if (j==22){
X[4]=X[4]+1
X[5]=X[5]-1
} else if (j==23){
X[2]=X[2]-1
X[5]=X[5]+1
} else if (j==24){
X[2]=X[2]+1
X[5]=X[5]-1
} else if (j==25){
X[3]=X[3]-1
X[2]=X[2]+1
} else if (j==26){
X[3]=X[3]+1
X[2]=X[2]-1
} else if (j==27){
X[3]=X[3]-1
X[7]=X[7]+1
} else if (j==28){
X[3]=X[3]+1
X[7]=X[7]-1
} else if (j==29){
X[8]=X[8]-1
X[4]=X[4]+1
} else if (j==30){
X[8]=X[8]+1
X[4]=X[4]-1
} else if (j==31){
X[4]=X[4]-1
X[7]=X[7]+1
} else if (j==32){
X[4]=X[4]+1
X[7]=X[7]-1
} else if (j==33){
X[6]=X[6]-1
X[8]=X[8]+1
} else if (j==34){
X[6]=X[6]+1
X[8]=X[8]-1
} else if (j==35){
X[3]=X[3]-1
X[4]=X[4]+1
} else if (j==36){
X[3]=X[3]+1
X[4]=X[4]-1
}
day.old <- day #Keep track of previous days
day=ceiling(ti)
if (day > day.old){
saved[(day.old+1):day,] <-
matrix(saved[day.old,], (day - day.old), 8, byrow=TRUE) # What was this intended to achieve?
saved[day,] <- X
cat("day =", day, X, "\n")
#cat('day:', sprintf('%7.4f',day.old), ' tail:', X[1], ' Anal:', X[2], ' LB:', X[3],' UB:',
# X[4],' Pelvic:', X[5],' Pectoral:', X[6],' dorsal:', X[7],' Head:', X[8], '\n')
}
}
return(saved)
}
#Suppose parasite prefer tail
b <- 0.5 #birth rate per day
d <- 0.14 #death rate
m <- 0.3 #movement rate
X0 <- c(2,0,0,0,0,0,0,0)# initial condition of gyro that prefers the tail
Ti <- 17 #finishing time
#set.seed(12)
Results <- Fishsim_model(b, d, m, X0, Ti)
Results
Both error messages suggest that at some point all values in the Q vector are 0, which causes the first error. Example : sample(3,1, prob = c(0,0,0)).
Consequently, the rate (Qt), which u are passing to the exponential distribution random generator is also 0 and NaN is returned, which causes the second error. Example : rexp(1,0)
Unfortunately, your code was hard for me to read, so I refactored it. You can find an augmented version below, which works with the example input. My guess is that there is an error somewhere causing Q to take the 0 state, you can trace it with some print statements and debug functionalities. You can further refactor this piece of code to make it even more readable and performant.
In general, you can investigate the mathematical conditions for the initial inputs to guarantee that the Q vector never falls in the 0 state. I am not sure if you are looking for pointers on how to do this, as well.
HTH
CHANGE_MATRIX <- matrix(
c(-1, 0, 1, 0, 0, 0, 0, 0
, 1, 0, -1, 0, 0, 0, 0, 0
, 0, 0, 0, -1, 0, 1, 0, 0
, 0, 0, 0, 1, 0, -1, 0, 0
, 0, 0, 0, -1, 1, 0, 0, 0
, 0, 0, 0, 1, -1, 0, 0, 0
, 0, -1, 0, 0, 1, 0, 0, 0
, 0, 1, 0, 0, -1, 0, 0, 0
, 0, 1, -1, 0, 0, 0, 0, 0
, 0, -1, 1, 0, 0, 0, 0, 0
, 0, 0, -1, 0, 0, 0, 1, 0
, 0, 0, 1, 0, 0, 0, -1, 0
, 0, 0, 0, 1, 0, 0, 0, -1
, 0, 0, 0, -1, 0, 0, 0, 1
, 0, 0, 0, -1, 0, 0, 1, 0
, 0, 0, 0, 1, 0, 0, -1, 0
, 0, 0, 0, 0, 0, -1, 0, 1
, 0, 0, 0, 0, 0, 1, 0, -1
, 0, 0, -1, 1, 0, 0, 0, 0
, 0, 0, 1, -1, 0, 0, 0, 0)
, ncol = 8
, byrow = T
)
UPDATE_LOCATION <- c(1, 3, 4, 6, 4, 5
, 2, 5, 3, 2, 3, 7
, 8, 4, 4, 7, 6, 8
, 3, 4)
UPDATE_WEIGHT <- c(1, 3, 5, 2, 5, 2
, 2, 2, 2, 2, 3, 2
, 2, 5, 4, 2, 2, 2
, 4, 5)
UPDATE_INDEX <- seq(17, 36)
BODY_PARTS <- c(' Tail'
,' Anal'
,' LB'
,' UB'
,' Pelvic'
,' Pectoral'
,' dorsal'
,' Head')
Fishsim_model <- function(b,d,m,X0,Ti){
#b=birth rate; d=death rate; m=movement rate; Ti=finishing time
#X0=initial distribution; X= states
X <- X0
Ti <- floor(Ti)
ti <- 0 # (initial) time
day <- 1
saved <- matrix(0, Ti+1, 8) #Matrix of zeros to save final results
saved[day,] <- X0
Q <- vector('numeric', 36)
Qt <- 0 # Qt = sum(Q) is departure rate from current state
while (ti < Ti){
#Calculate rates
Q[1:8] <- X*b
Q[9:16] <- X*d
Q[UPDATE_INDEX]<-X[UPDATE_LOCATION[seq_along(UPDATE_INDEX)]]*
(m*(1/UPDATE_WEIGHT[seq_along(UPDATE_INDEX)]))
Qt <- sum(Q)
# time for next jump
ti <- ti + rexp(1, Qt)
# new state
j <- sample(36, 1, prob = Q)
if (j <= 8) {
X[j] <- X[j] + 1
} else if (j <= 16){
X[j-8] <- X[j-8] - 1
} else{
X <- X + CHANGE_MATRIX[j-16, ]
}
day.old <- day #Keep track of previous days
day <- ceiling(ti)
if (day > day.old){
# What was this intended to achieve?
# saved[(day.old+1):day,] <- matrix(saved[day.old,]
# , (day - day.old)
# , 8
# , byrow=TRUE)
saved[day, ] <- X
cat(
paste('day:', day)
, '\n'
, paste(BODY_PARTS, ':', X)
, '\n'
)
}
}
return(saved)
}
#Suppose parasite prefer tail
b <- 0.5 #birth rate per day
d <- 0.14 #death rate
m <- 0.3 #movement rate
X0 <- c(2,0,0,0,0,0,0,0)# initial condition of gyro that prefers the tail
Ti <- 17 #finishing time
#set.seed(12)
Results <- Fishsim_model(b, d, m, X0, Ti)
Results
I have been able to figure the way out to prevent the errors based previous recommendation received here. This will help me run the model a number of times without any error message. I just needed to break the loop from running when the sum of rates equals 0.
Below is the single code of line I needed to include in my codes;
enter code here
Qt=sum(Q)
if (Qt == 0) break #Just this line code to help break the loop and return to the next
ti <- ti + rexp(1,Qt)
j=sample(152,1,prob=Q)

Combined subsetting in R?

I trying to subset 3 ys for when xs are -1, 0, and 1 in my code below. But I was hoping to do this all at once using y[c(x == -1, x == 0, x == 1)] which apparently does not work (see below).
Any better way to do this subsetting all at once?
x = seq(-1, 1, l = 1e4)
y = dcauchy(x, 0, sqrt(2)/2)
y[c(x == -1, x == 0, x == 1)] ## This subsetting format doesn't work
We can do this.
y[x == -1| x == 0| x == 1]
Or this
y[x %in% c(-1, 0, 1)]

R - Plot a region described by planes with rgl

I want to plot a polyhedron, which is described by the following inequalities:
3*x+5*y+9*z<=500
4*x+5*z<=350
2*y+3*z<=150
x,y,z>=0
It is a linear program. The objective function is:
4*x+3*y+6*z
The polyhedron is the feasible region for this program.
I am able to plot the inequalities as planes, which should describe the polyhedron
(Note that this is my first try with rgl, so the code is kinda messy. if you want to improve it, please feel free to do so):
# setup
x <- seq(0,9,length=20)*seq(0,9,length=20)
y <- x
t <- x
f1 <- function(x,y){y=70-0.8*x}
z1 <- outer(x,y,f1)
f2 <- function(x,y){500/9-x/3-(5*y)/9}
z2 <- outer(x,y,f2)
f3 <- function(x,y){t=50-(2*y)/3}
z3 <- outer(x,y,f3)
# plot planes with rgl
uM = matrix(c(0.72428817, 0.03278469, -0.68134511, 0,
-0.6786808, 0.0555667, -0.7267077, 0,
0.01567543, 0.99948466, 0.05903265, 0,
0, 0, 0, 1),
4, 4)
library(rgl)
open3d(userMatrix = uM, windowRect = c(0, 0, 400, 400))
rgl.pop("lights")
light3d(diffuse='white',theta=0,phi=20)
light3d(diffuse="gray10", specular="gray25")
rgl.light(theta = 0, phi = 0, viewpoint.rel = TRUE, ambient = "#FFFFFF",
diffuse = "#FFFFFF", specular = "#FFFFFF", x=30, y=30, z=40)
rgl.light(theta = 0, phi = 0, viewpoint.rel = TRUE, ambient = "#FFFFFF",
diffuse = "#FFFFFF", specular = "#FFFFFF", x=0, y=0, z=0)
bg3d("white")
material3d(col="white")
persp3d(x,y,z3,
xlim=c(0,100), ylim=c(0,100), zlim=c(0,100),
xlab='x', ylab='y', zlab='z',
col='lightblue',
ltheta=100, shade=0, ticktype = "simple")
surface3d(x, y, z2, col='orange', alpha=1)
surface3d(t, y, z1, col='pink', alpha=1, smooth=TRUE)
Now I want to plot the region that is described by the planes with
x,y,z>=0.
But I don't know how to do it. I tried to do it like this:
x <- seq(0,9,length=20)*seq(0,9,length=20)
y <- x
z <- x
f4 <- function(x,y,t){
cond1 <- 3*x+5*y+9*z<=500
cond2 <- 4*x+5*z<=350
cond3 <- 2*y+3*z<=150
ifelse(cond1, 3*x+5*y+9*z,
ifelse(cond2, 4*x+5*z,
ifelse(cond3, 2*y+3*z,0)))
}
f4(x,y,z)
z4 <- outer(x,y,z,f4) # ERROR
But this is the point where I'm stuck. outer() is defined only for 2 variables, but I have three. How can I move on from here?
You can compute the vertices of the polyhedron by intersecting the planes 3 at a time
(some of the intersections are outside the polyhedron, because of other inequalities:
you have to check those as well).
Once you have the vertices, you can try to connect them.
To identify which are on the boundary, you can take the middle of the segment,
and check if any inequality is satisfied as an equality.
# Write the inequalities as: planes %*% c(x,y,z,1) <= 0
planes <- matrix( c(
3, 5, 9, -500,
4, 0, 5, -350,
0, 2, 3, -150,
-1, 0, 0, 0,
0, -1, 0, 0,
0, 0, -1, 0
), nc = 4, byrow = TRUE )
# Compute the vertices
n <- nrow(planes)
vertices <- NULL
for( i in 1:n )
for( j in 1:n)
for( k in 1:n )
if( i < j && j < k ) try( {
# Intersection of the planes i, j, k
vertex <- solve(planes[c(i,j,k),-4], -planes[c(i,j,k),4] )
# Check that it is indeed in the polyhedron
if( all( planes %*% c(vertex,1) <= 1e-6 ) ) {
print(vertex)
vertices <- rbind( vertices, vertex )
}
} )
# For each pair of points, check if the segment is on the boundary, and draw it
library(rgl)
open3d()
m <- nrow(vertices)
for( i in 1:m )
for( j in 1:m )
if( i < j ) {
# Middle of the segment
p <- .5 * vertices[i,] + .5 * vertices[j,]
# Check if it is at the intersection of two planes
if( sum( abs( planes %*% c(p,1) ) < 1e-6 ) >= 2 )
segments3d(vertices[c(i,j),])
}

Resources