How to make faster approximation of data by sinusoids - r

I have a function that generates a sine wave
my.sin <- function(vec,a,f,p) a*sin(f*vec+p)
vec = vector indices
a = amplitude
f = frequency
p = phase
I also have some data my_var that I want to approximate with several sinusoids
set.seed(22)
my_var <- rnorm(100)
plot(my_var,t="l")
There is also a fitness function that calculates the approximation error of the sum of two sinusoids,but there can be any number of sinusoids
fit <- function(x,test=F){
vec <- 1:length(my_var)
s1 <- my.sin(vec = vec,a = x[1],f = x[2],p = x[3])
s2 <- my.sin(vec = vec,a = x[4],f = x[5],p = x[6])
res_sin <- s1+s2
err <- sqrt(sum((res_sin - my_var) ^ 2))
if(test) return(res_sin)
return( err/-1 )
}
Next, I use a genetic algorithm to find the best solution.
library(GA)
GA <- ga("real-valued",
fit,
lower = rep(-5,6),
upper = rep( 5,6),
maxiter = 300,
popSize = 300)
sol <- tail(GA#solution,1)[1,]
ga_sin <- fit(sol,test = T)
lines(ga_sin,col=4,lwd=2)
best_sin_comb <- matrix(sol,ncol = 3,byrow = T)
colnames(best_sin_comb) <- c("amplitude","frequency","phase")
print(best_sin_comb)
result
amplitude frequency phase
[1,] -0.3435402 1.5458888 1.8904578
[2,] -0.4326791 -0.4886035 0.5606401
My question is: can the approximation be made more efficient in terms of time spent. Perhaps a different search algorithm or something else ..
Also I would like to keep compatibility with the function my.sin

Related

R: object .... not found

So I'm trying to process the data ("final_ts") in order to make a forecast for the time series using kernel functions and doing parallel computing. The analysis is made this way: 1) analyse the empirical time series, 2) run a standard variable
selection to subset only those variables and their time-lags that provide the best validation error. 3) Run the same analysis described above to choose the optimal regularization parameters and kernel function of the regularized algorithm. As a result I show the RMSE (root mean squared error).
The code is not mine, and I'm trying to set it without problems, but as I do not have so much experience, I can't understand how to solve (I've spent 2 days trying to find the solution so if you help me I would be so grateful) the problem which occured: "The object '....' not found".
So the MAIN CODE looks like this (I'll try to make explanation on what happens, please don't judge me):
#download the libraries:
rm(list=ls(all=TRUE))
suppressMessages(library(Matrix))
suppressMessages(library(quantreg))
suppressMessages(library(parallel))
suppressMessages(library(compiler))
suppressMessages(library(lars))
suppressMessages(library(elasticnet))
suppressMessages(library(caret))
options(warn=-1)
#####################################################################################
#Download the sources (I'll show them in the end as a code)
###########Take the file###
ShowPlot = FALSE
lags = TRUE
ModelName = 'final_ts'
FileName = paste(ModelName, '.txt', sep = '')
########Calculate the logspace and the standard error functions #################
logspace <- function(d1, d2, n) exp(log(10)*seq(d1, d2, length.out=n))
std_err <- function(x) sd(x)/sqrt(length(x))
############# Choose the kernel function: we have 4 of them, but we try the second one #####
Kernel.Options = c('Exponential.Kernel', 'Epanechnikov.Kernel', 'TriCubic.Kernel', 'Matern.Kernel')
Regression.Kernel = Kernel.Options[1]
############# Choose the parameters for cross validation ####
lambda = logspace(-3,0,15)
if(Regression.Kernel == 'Exponential.Kernel'){
tht = seq(from = 0., to = 10, length = 30)
}else{
tht = seq(from = 0.1, to = 3, length = 20)
}
parameters_on_grid = expand.grid(tht, lambda)
### Read Time series
d = as.matrix(read.table(FileName, header= T))
######################
original.Embedding = c('Pro', 'Syn','Piceu')
original.TargetList = original.Embedding
d = d[, original.Embedding]
#### Here you take combinations of lags (best lag are 1 - 2) #####
x.lag = 1; y.lag = 2; z.lag = 1
sp.lag.selection = c(x.lag, y.lag, z.lag)
lagged.time.series = make.lagged.ts(d, sp.lag.selection)
d = lagged.time.series$time.series
original.col = lagged.time.series$original.variables
if(lags == TRUE){ var.sel = original.col; }else{ var.sel = colnames(d)}
##### Names and embedding in the laged dataset
if(lags == TRUE){ colnames(d) = Embedding = TargetList = LETTERS[1:ncol(d)]}else{
Embedding = TargetList = original.Embedding
}
##### length of training and test set (2 points for testing, 28 - for training)
length.testing = 2
length.training = nrow(d) - length.testing
#### Preserve training for the interactions
ts.train.preserved = d[1:length.training, var.sel]
std.ts.train = Standardizza(ts.train.preserved)
#### Preserve testing for the test (you want your algorithm to learn the real structure of the model)
ts.test.preserved = d[(length.training + 1):nrow(d), var.sel]
#### Training set:
d.training = Standardizza(d[1:length.training, ])
#### You now need to standardize the test set using mean and sd of the training set
d.testing = Standardizza.test(ts.test.preserved,ts.train.preserved)
############## Prepare for parallel computing
Lavoratori = detectCores() - 2
cl <- parallel::makeCluster(Lavoratori, setup_strategy = "sequential")
####
RegressionType = ELNET_fit_
alpha = 0.85
### should you compute all the variables or not?
BestModel = BestModelLOOCV(cl, d.training, TargetList, Embedding, parameters_on_grid, RegressionType,alpha)
I also found a fourmula for calculation of kernel function (it may be put in a SPECIAL r (SOURCE 1)):
Exponential.Kernel <- function(dst, theta){
dbar <- mean(dst)
krnl <- exp(-theta*dst/dbar)
return(krnl)
}
Exponential.Kernel <- cmpfun(Exponential.Kernel)
The formulas for finding the best leave-one-out cross-validation parameters is below (SOURCE 2):
########################### Cross Validation (Leave-one-out) ##################################
BestModelLOOCV <- function(cl, X, TargetList, Embedding, grid, RegressionType,alpha){
mine_output = Jacobian_(cl, X, TargetList, Embedding, grid, RegressionType,alpha)
theta_opt = mine_output$th
lambda_opt = mine_output$lm
mine_c0 = mine_output$c0
mine_output = mine_output$J
J_ = list()
C0_ = do.call(cbind, lapply(1:ncol(X), function(x, M) unlist(M[[x]]), mine_c0))
colnames(C0_) = sapply(TargetList,function(x) paste("c0_", x, sep = ""))
for(k in 1:(nrow(X) - 1)){
J_[[k]] = do.call(rbind, lapply(1:ncol(X), function(x, M, i) unlist(M[[x]][i,]), mine_output, k))
rownames(J_[[k]]) = Embedding
colnames(J_[[k]]) = Embedding
}
BestCoefficients = list()
BestCoefficients$J = J_
BestCoefficients$c0 = C0_
BestParameters = list()
BestParameters$BestTH = theta_opt
BestParameters$BestLM = lambda_opt
return(list(BestCoefficients = BestCoefficients, BestParameters = BestParameters))
}
#####Compute the jacobian
Jacobian_ <- function(cl, X, TargetList, Embedding, grid, RegressionType,alpha){
J = c0 = list()
th = lm = c()
n_ = 1
FUN = match.fun(RegressionType)
for(trg in TargetList){
RegularizedParameters <- LOOCrossValidation(cl, X, trg, Embedding, grid, RegressionType,alpha)
########## Now compute the optimum regularized coefficients
J[[n_]] = FUN(X, trg, Embedding, RegularizedParameters$BestTH, RegularizedParameters$BestLM,alpha)
th = c(th, RegularizedParameters$BestTH)
lm = c(lm, RegularizedParameters$BestLM)
c0[[n_]] = J[[n_]]$c0
J[[n_]] = J[[n_]][-1]
n_ = n_ + 1
}
return(list(J = J, c0 = c0, th = th, lm = lm))
}
In order to compute the elastic-net regularization function you may use this formula (SOURCE 3):
ELNET_fit_ <- function(time.series, targ_col, Embedding, theta, lambda,alp){
Edim <- length(Embedding)
coeff_names <- sapply(colnames(time.series),function(x) paste("d", targ_col, "d", x, sep = ""))
block <- cbind(time.series[2:dim(time.series)[1],targ_col],time.series[1:(dim(time.series)[1]-1),])
block <- as.data.frame(apply(block, 2, function(x) (x-mean(x))/sd(x)))
lib <- 1:dim(block)[1]
pred <- 1:dim(block)[1]
coeff <- array(0,dim=c(length(pred),Edim + 1))
colnames(coeff) <- c('c0', coeff_names)
coeff <- as.data.frame(coeff)
for (ipred in 1:length(pred)){
libs = lib[-pred[ipred]]
q <- matrix(as.numeric(block[pred[ipred],2:dim(block)[2]]),
ncol=Edim, nrow=length(libs), byrow = T)
distances <- sqrt(rowSums((block[libs,2:dim(block)[2]] - q)^2))
### Kernel
Krnl = match.fun(Regression.Kernel)
Ws = Krnl(distances, theta)
############ Fit function
x = as.matrix(block[libs,2:dim(block)[2]])
y = as.matrix(block[libs,1])
x = x[seq_along(y), ]
y = y[seq_along(y)]
Ws = Ws[seq_along(y)]
x = Ws * cbind(1, x)
y = Ws * y
fit <- enet(x, y, lambda = lambda, normalize = TRUE, intercept = FALSE)
coeff[ipred,] <- predict(fit, s = alp, type="coefficients", mode="fraction")$coefficients
}
return(coeff)
}
ELNET_fit_ <- cmpfun(ELNET_fit_)
The auxiliary formulas for computation are as follows (SOURCE 4):
TakeLag <- function(X, species.to.lag, num.lag){
tmp = matrix(0, nrow(X), num.lag)
tmp[,1] = X[,species.to.lag]
tmp[1, 1] = NA
tmp[2:nrow(X), 1] = X[1:(nrow(X) - 1), species.to.lag]
if(num.lag > 1){
for(lag. in 2:num.lag){
tmp[,lag.] = X[,species.to.lag]
tmp[1, lag.] = NA
tmp[2:nrow(X), lag.] = tmp[1:(nrow(tmp) - 1), lag.-1]
}
}
tmp
}
make.lagged.ts <- function(X,sp.lag.selection ){
### X = time series
### sp.lag is a vector whose entry are the lags of each variable
### e.g., sp.lag = c(x.lag, y.lag, ..., u.lag)
s = list()
for(i in 1:length(sp.lag.selection)){
Lag.sp = TakeLag(X, original.Embedding[i], sp.lag.selection[i])
s[[i]] = cbind(X[,original.Embedding[i]], Lag.sp)
}
X = do.call(cbind,s)
### Remove the NA
X = X[-c(1:max(sp.lag.selection)),]
### Save the position of the unlagged variables
original.col = c()
for(k in 1:length(sp.lag.selection)){
if(k == 1){ original.col = c(original.col, 1)}else{
num.lags = sum(unlist(lapply(1:(k-1), function(x,X) X[x], sp.lag.selection)))
original.col = c(original.col, k + num.lags )
}
}
return(list(time.series = X, original.variables = original.col))
}
take.coeff <- function(X, col.to.extract, original.emb){
### To use when prediction are made using lagged variables
### Take as input the sequence X of Jacobian along the attractor
### and the species to look at
### return a new sequence of Jacobian of the interaction among those species
m = lapply(1:length(X$J), function(t, M, specie) M$J[[t]][specie,specie],
X, col.to.extract)
for(i in 1:length(m)){
colnames(m[[i]]) = rownames(m[[i]]) =original.emb
}
return(m)
}
Standardizza <- function(X){
### This return y = (x-meanx)/stdx
for(i in 1:ncol(X)){
X[,i] = (X[,i]- mean(X[,i]))/sd(X[,i])
}
return(X)
}
Standardizza.test <- function(X, Y){
### X = test set
### Y = training set
### This return y = (x-meanY)/stdY
for(i in 1:ncol(X)){
X[,i] = (X[,i]- mean(Y[,i]))/sd(Y[,i])
}
return(X)
}
###########################
#### Here you compute the quality of the forecast as mean correlation coefficient
The problem in the main code sounds like: object 'Regression.Kernel' not found, but I see it in the code, it's written. Maybe the problem is connected with the type of it? But if I take away the quotes in order to make it a "closure", I cannot impose the function restrictions.
Please, help me if you can as I don't know how to solve.
The original dataset ("final_ts.txt"):
decy Temp CTD_S OxFix Pro Syn Piceu Naneu
2011.74221 27.60333 36.20700 27.26667 58638.33333 13107.00000 799.66667 117.66667
2011.74401 26.97950 36.13400 27.05000 71392.50000 13228.50000 1149.00000 116.50000
2011.74617 24.99750 35.34450 24.80000 264292.00000 27514.00000 2434.50000 132.50000
2011.74692 24.78400 35.25800 25.82500 208996.50000 39284.00000 3761.75000 220.75000
2011.74774 27.34225 35.86800 27.82500 114617.25000 23115.00000 2337.00000 139.75000
2011.74950 26.47875 36.18175 27.20000 97008.00000 9775.75000 855.50000 77.50000
2011.75583 26.86500 36.14575 27.47500 76255.00000 10226.75000 783.00000 99.50000
2011.75654 27.04550 36.04950 27.60000 95017.75000 10546.25000 915.25000 77.75000
2011.75962 27.06567 36.46367 26.56667 75750.00000 10194.33333 687.00000 44.00000
2011.76101 27.44700 36.48150 27.90000 38556.50000 8204.75000 791.25000 118.75000
2011.76169 27.32325 36.50075 27.80000 29848.50000 8995.50000 727.00000 159.25000
2011.76245 26.87050 36.57350 26.40000 36323.50000 10897.00000 792.00000 87.50000
2011.76349 27.43900 36.89325 27.90000 17308.50000 9678.50000 559.00000 149.00000
2011.77171 26.74050 36.90550 26.10000 20976.50000 7516.00000 489.50000 41.50000
2011.77224 26.53500 36.77500 27.22500 27229.00000 7578.00000 606.75000 159.50000
2011.77288 26.65450 36.78500 27.32500 37897.50000 10493.50000 1008.75000 209.50000
2011.77444 27.24150 36.73800 26.80000 15551.00000 8159.50000 479.00000 70.50000
2011.77505 26.67560 36.74240 27.30000 27887.80000 5290.80000 510.00000 101.20000
2011.77568 27.65125 36.69225 28.10000 12850.00000 9944.75000 640.75000 120.00000
2011.77693 28.11500 36.32750 27.85000 5694.00000 10288.50000 507.00000 32.00000
2011.77751 28.61950 36.26325 28.72500 20486.75000 10465.00000 430.50000 82.75000
2011.77814 28.60425 36.23100 28.70000 27974.50000 6977.25000 554.00000 80.50000
2011.77968 28.47200 35.69000 28.40000 126778.00000 2840.00000 537.00000 27.00000
2011.78087 28.89400 35.60650 28.35000 49250.00000 5533.00000 1004.00000 5.50000
2011.78190 28.74100 35.46200 28.80000 35698.00000 1298.00000 308.00000 23.00000
2011.78713 28.80500 35.50100 28.70000 99450.00000 5410.00000 637.50000 50.50000
2011.78887 28.39250 35.90900 28.25000 116562.00000 3758.50000 582.50000 60.00000
2011.79078 28.10550 36.40150 28.20000 13403.00000 11285.00000 472.00000 73.50000
2011.79261 27.25650 36.78350 27.45000 11205.00000 10576.00000 630.00000 74.00000
Please, help if you have any guess as I don't have an idea what has gone wrong.

Genetic algorythm (GA) to select the optimal n values of a vector

I have to choose 10 elements of a vector to maximizes a function. Since the vector is pretty long there are to many possibilities (~1000 choose 10) to compute them all. So I started to look into the GA package to use a genetic algorithm.
I came up with this MWE:
values <- 1:1000
# Fitness function which I want to maximise
f <- function(x){
# Choose values
y <- values[x]
# From the first 10 sum up the odd values.
y <- ifelse(y %% 2 != 0, y, 0)
y <- y[1:10]
return(sum(y))
}
# Maximum value of f for this example
y <- ifelse(values %% 2 != 0, values, 0)
sum(sort(y, decreasing = TRUE)[1:10])
# [1] 9900
# Genetic algorithm
GA <- ga(type = "permutation", fitness = f, lower = rep(1, 10), upper = rep(1000, 10), maxiter = 100)
summary(GA)
The results are a bit underwhelming. From summary(GA), I get the feeling that the algorithm always permutates all 1000 values (the solution goes from x1 to x1000) which leads to an inefficient optimization. How can I tell the algorithm that it should only should use 10 values (so the solution is x1 .. x10)?
You should read https://www.jstatsoft.org/article/view/v053i04. You don't have permutation problem but selection one hence you should use binary type of genetic algorithm. Because you want to select exclusively 10 (10 ones and 990 zeroes) you should probably write your own genetic operators because that is constraint that will hardly ever be satisfied by default operators (with inclusion of -Inf in fitness function if you have more than 10 zeroes). One approach:
Population (k tells how much ones you want):
myInit <- function(k){
function(GA){
m <- matrix(0, ncol = GA#nBits, nrow = GA#popSize)
for(i in seq_len(GA#popSize))
m[i, sample(GA#nBits, k)] <- 1
m
}
}
Crossover
myCrossover <- function(GA, parents){
parents <- GA#population[parents,] %>%
apply(1, function(x) which(x == 1)) %>%
t()
parents_diff <- list("vector", 2)
parents_diff[[1]] <- setdiff(parents[2,], parents[1,])
parents_diff[[2]] <- setdiff(parents[1,], parents[2,])
children_ind <- list("vector", 2)
for(i in 1:2){
k <- length(parents_diff[[i]])
change_k <- sample(k, sample(ceiling(k/2), 1))
children_ind[[i]] <- if(length(change_k) > 0){
c(parents[i, -change_k], parents_diff[[i]][change_k])
} else {
parents[i,]
}
}
children <- matrix(0, nrow = 2, ncol = GA#nBits)
for(i in 1:2)
children[i, children_ind[[i]]] <- 1
list(children = children, fitness = c(NA, NA))
}
Mutation
myMutation <- function(GA, parent){
ind <- which(GA#population[parent,] == 1)
n_change <- sample(3, 1)
ind[sample(length(ind), n_change)] <- sample(setdiff(seq_len(GA#nBits), ind), n_change)
parent <- integer(GA#nBits)
parent[ind] <- 1
parent
}
Fitness (your function adapted for binary GA):
f <- function(x, values){
ind <- which(x == 1)
y <- values[ind]
y <- ifelse(y %% 2 != 0, y, 0)
y <- y[1:10]
return(sum(y))
}
GA:
GA <- ga(
type = "binary",
fitness = f,
values = values,
nBits = length(values),
population = myInit(10),
crossover = myCrossover,
mutation = myMutation,
run = 300,
pmutation = 0.3,
maxiter = 10000,
popSize = 100
)
Chosen values
values[which(GA#solution[1,] == 1)]

Possible ways to incorporate topography in a correlated random walk in R?

I was wondering which possibilities there are for incorporating topography in a correlated random walk in R. I have a digital elevation model (DEM) of the study area. I would like for my random walk to avoid areas with a steep slope.
walk <- function(x0, y0, head0, n, parameterMu, parameterRho, parameterMean, parameterSd)
{
# Get nr of individuals, call it k
k = length(x0)
# Create list to hold data
all.paths <- list()
for (j in 1:k)
{
# Create structure to hold data
steps <- data.frame(matrix(0,n,6))
colnames(steps) <- c("id","x", "y", "steplength", "heading", "turningangle")
# Insert the id, starting location and heading
steps[,"id"] = j
steps[1,"x"] = x0[j]
steps[1,"y"] = y0[j]
steps[1,"heading"] = head0[j]
# Simulate steps
for(i in 2:n)
{
# Draw step length and turning angle, compute heading
steplength = rnorm(n = 1, mean = parameterMean, sd = parameterSd)
turningangle = as.numeric(rwrappedcauchy(n = 1, mu = parameterMu, rho = parameterRho))
newbearing = as.numeric(circular(steps[i-1,"heading"]) + circular(turningangle)) %% (2*pi)
# Get new location
next.xy <- movement(x0=steps[i-1,"x"], y0=steps[i-1,"y"], step=steplength, heading=newbearing)
# Store output (xy on row i, steplength/heading on row i-1)
steps[i,"x"] <- next.xy[1,"x"]
steps[i,"y"] <- next.xy[1,"y"]
steps[i,"steplength"] <- next.xy[1,"step"]
steps[i,"heading"] <- newbearing
steps[i,"turningangle"] <- turningangle
# Store trajectory in list
all.paths[[j]] <- steps
}
# Return output
return(all.paths)
}
The movement function:
movement <- function(x0, y0, step, heading)
{
x_new <- x0 + sin(heading)*step
y_new <- y0 + cos(heading)*step
move.temp <- data.frame(x = x_new,
y = y_new,
step = step,
head = heading)
return(move.temp)
}

Best way to solve an integral including a nonparametric density and distribution

Suppose that I want to solve a function containing two integrals like (this is an example, the actual function is uglier)
where a and b are the boundaries, c and d are known parameters and f(x) and F(x) are the density and distribution of the random variable x. In my problem f(x) and F(x) are nonparametrically found, so that I know their values only for certain specific values of x. How would you set the integral?
I did:
# Create the data
val <- runif(300, min=1, max = 10) #use the uniform distribution
CDF <- (val - 1)/(10 - 1)
pdf <- 1 / (10 - 1)
data <- data.frame(val = val, CDF = CDF, pdf = pdf)
c = 2
d = 1
# Inner integral
integrand1 <- function(x) {
i <- which.min(abs(x - data$val))
FF <- data$CDF[i]
ff <- data$pdf[i]
(1 - FF)^(c/d) * ff
}
# Vectorize the inner integral
Integrand1 <- Vectorize(integrand1)
# Outer integral
integrand2 <- function(x){
i <- which.min(abs(x - data$val))
FF <- data$CDF[i]
ff <- data$pdf[i]
(quadgk(Integrand1, x, 10) / FF) * c * ff
}
# Vectorize the outer integral
Integrand2 <- Vectorize(integrand2)
# Solve
require(pracma)
quadgk(Integrand2, 1, 10)
The integral is extremely slow. Is there a better way to solve this? Thank you.
---------EDIT---------
In my problem the pdf and CDF are computed from a vector of values v as follows:
# Create the original data
v <- runif(300, min = 1, max = 10)
require(np)
# Compute the CDF and pdf
v.CDF.bw <- npudistbw(dat = v, bandwidth.compute = TRUE, ckertype = "gaussian")
v.pdf.bw <- npudensbw(dat = v, bandwidth.compute = TRUE, ckertype = "gaussian")
# Extend v on a grid (I add this step because the v vector in my data
# is not very large. In this way I approximate the estimated pdf and CDF
# on a grid)
val <- seq(from = min(v), to = max(v), length.out = 1000)
data <- data.frame(val)
CDF <- npudist(bws = v.CDF.bw, newdata = data$val, edat = data )
pdf <- npudens(bws = v.pdf.bw, newdata = data$val, edat = data )
data$CDF <- CDF$dist
data$pdf <- pdf$dens
Have you considered using approxfun?
It takes vectors x and y and gives you a function that linearly interpolates between those. So for example, try
x <- runif(1000)+runif(1000)+2*(runif(1000)^2)
dx <- density(x)
fa <- approxfun(dx$x,dx$y)
curve(fa,0,2)
fa(0.4)
You should be able to call it using your gridded evaluations. It may be faster than what you're doing (as well as more accurate)
(edit: yes, as you say, splinefun should be fine if its fast enough for your needs)

Multi-data likelihood function and mle2 function from bbmle package in R

I have written a custom likelihood function that fits a multi-data model that integrates mark-recapture and telemetry data (sensu Royle et al. 2013 Methods in Ecology and Evolution). The likelihood function is designed to be flexible in terms of whether and how many covariates are specified for different linear models in different likelihood components which is determined by values supplied as function arguments (i.e., data matrices "detcovs" and "dencovs" in my code). The likelihood function works when I directly supply it to optimization functions (e.g., optim or nlm), but does not play nice with the mle2 function in the bbmle package. My problem is that I continually run into the following error: "some named arguments in 'start' are not arguments to the specified log-likelihood function". This is my first attempt at writing custom likelihood functions so I'm sure there are general coding conventions of which I'm unaware that make such tasks much more efficient and amendable to the mle2 function. Below is my likelihood function, code creating the staring value objects, and code calling the mle2 function. Any advice how to solve the error problem and general comments on writing cleaner functions is welcome. Many thanks in advance.
Edit: As requested, I have simplified the likelihood function and provided code to simulate reproducible data to which the model can be fit. Included in the simulation code are 2 custom functions and use of the raster function from the raster package. Hopefully, I have sufficiently simplified everything to enable others to troubleshoot. Again, many thanks for your help!
Jared
Likelihood function:
CSCR.RSF.intlik2.EXAMPLE <- function(alpha0,sigma,alphas=NULL,betas=NULL,n0,yscr=NULL,K=NULL,X=X,trapcovs=NULL,Gden=NULL,Gdet=NULL,ytel=NULL,stel=NULL,
dencovs=NULL,detcovs=NULL){
#
# this version of the code handles a covariate on log(Density). This is starting value 5
#
# start = vector of starting values
# yscr = nind x ntraps encounter matrix
# K = number of occasions
# X = trap locations
# Gden = matrix with grid cell coordinates for density raster
# Gdet = matrix with gride cell coordinates for RSF raster
# dencovs = all covariate values for all nGden pixels in density raster
# trapcovs = covariate value at trap locations
# detcovs = all covariate values for all nGrsf pixels in RSF raster
# ytel = nguys x nGdet matrix of telemetry fixes in each nGdet pixels
# stel = home range center of telemetered individuals, IF you wish to estimate it. Not necessary
# alphas = starting values for RSF/detfn coefficients excluding sigma and intercept
# alpha0 = starting values for RSF/detfn intercept
# sigma = starting value for RSF/detfn sigma
# betas = starting values for density function coefficients
# n0 = starting value for number of undetected individuals on log scale
#
n0 = exp(n0)
nGden = nrow(Gden)
D = e2dist(X,Gden)
nGdet <- nrow(Gdet)
alphas = alphas
loglam = alpha0 -(1/(2*sigma*sigma))*D*D + as.vector(trapcovs%*%alphas) # ztrap recycled over nG
psi = exp(as.vector(dencovs%*%betas))
psi = psi/sum(psi)
probcap = 1-exp(-exp(loglam))
#probcap = (exp(theta0)/(1+exp(theta0)))*exp(-theta1*D*D)
Pm = matrix(NA,nrow=nrow(probcap),ncol=ncol(probcap))
ymat = yscr
ymat = rbind(yscr,rep(0,ncol(yscr)))
lik.marg = rep(NA,nrow(ymat))
for(i in 1:nrow(ymat)){
Pm[1:length(Pm)] = (dbinom(rep(ymat[i,],nGden),rep(K,nGden),probcap[1:length(Pm)],log=TRUE))
lik.cond = exp(colSums(Pm))
lik.marg[i] = sum( lik.cond*psi )
}
nv = c(rep(1,length(lik.marg)-1),n0)
part1 = lgamma(nrow(yscr)+n0+1) - lgamma(n0+1)
part2 = sum(nv*log(lik.marg))
out = -1*(part1+ part2)
lam = t(exp(a0 - (1/(2*sigma*sigma))*t(D2)+ as.vector(detcovs%*%alphas)))# recycle zall over all ytel guys
# lam is now nGdet x nG!
denom = rowSums(lam)
probs = lam/denom # each column is the probs for a guy at column [j]
tel.loglik = -1*sum( ytel*log(probs) )
out = out + tel.loglik
out
}
Data simulation code:
library(raster)
library(bbmle)
e2dist <- function (x, y){
i <- sort(rep(1:nrow(y), nrow(x)))
dvec <- sqrt((x[, 1] - y[i, 1])^2 + (x[, 2] - y[i, 2])^2)
matrix(dvec, nrow = nrow(x), ncol = nrow(y), byrow = F)
}
spcov <- function(R) {
v <- sqrt(nrow(R))
D <- as.matrix(dist(R))
V <- exp(-D/2)
cov1 <- t(chol(V)) %*% rnorm(nrow(R))
Rd <- as.data.frame(R)
colnames(Rd) <- c("x", "y")
Rd$C <- as.numeric((cov1 - mean(cov1)) / sd(cov1))
return(Rd)
}
set.seed(1234)
co <- seq(0.3, 0.7, length=5)
X <- cbind(rep(co, each=5),
rep(co, times=5))
B <- 10
co <- seq(0, 1, length=B)
Z <- cbind(rep(co, each=B), rep(co, times=B))
dencovs <- cbind(spcov(Z),spcov(Z)[,3]) # ordered as reading raster image from left to right, bottom to top
dimnames(dencovs)[[2]][3:4] <- c("dencov1","dencov2")
denr.list <- vector("list",2)
for(i in 1:2){
denr.list[[i]] <- raster(
list(x=seq(0,1,length=10),
y=seq(0,1,length=10),
z=t(matrix(dencovs[,i+2],10,10,byrow=TRUE)))
)
}
B <- 20
co <- seq(0, 1, length=B)
Z <- cbind(rep(co, each=B), rep(co, times=B))
detcovs <- cbind(spcov(Z),spcov(Z)[,3]) # ordered as reading raster image from left to right, bottom to top
dimnames(detcovs)[[2]][3:4] <- c("detcov1","detcov2")
detcov.raster.list <- vector("list",2)
trapcovs <- matrix(0,J,2)
for(i in 1:2){
detr.list[[i]] <- raster(
list(x=seq(0,1,length=20),
y=seq(0,1,length=20),
z=t(matrix(detcovs[,i+2],20,20,byrow=TRUE)))
)
trapcovs[,i] <- extract(detr.list[[i]],X)
}
alpha0 <- -3
sigma <- 0.15
alphas <- c(1,-1)
beta0 <- 3
betas <- c(-1,1)
pixelArea <- (dencovs$y[2] - dencovs$y[1])^2
mu <- exp(beta0 + as.matrix(dencovs[,3:4])%*%betas)*pixelArea
EN <- sum(mu)
N <- rpois(1, EN)
pi <- mu/sum(mu)
s <- dencovs[sample(1:nrow(dencovs), size=N, replace=TRUE, prob=pi),1:2]
J <- nrow(X)
K <- 10
yc <- d <- p <- matrix(NA, N, J)
D <- e2dist(s,X)
loglam <- t(alpha0 - t((1/(2*sigma*sigma))*D*D) + as.vector(trapcovs%*%alphas))
p <- 1-exp(-exp(loglam))
for(i in 1:N) {
for(j in 1:J) {
yc[i,j] <- rbinom(1, K, p[i,j])
}
}
detected <- apply(yc>0, 1, any)
yscr <- yc[detected,]
ntel <- 5
nfixes <- 100
poss.tel <- which(s[,1]>0.2 & s[,1]<0.8 & s[,2]>0.2 & s[,2]<0.8)
stel.id <- sample(poss.tel,ntel)
stel <- s[stel.id,]
ytel <- matrix(NA,ntel,nrow(detcovs))
d <- e2dist(stel,detcovs[,1:2])
lam <- t(exp(1 - t((1/(2*sigma*sigma))*d*d) + as.vector(as.matrix(detcovs[,3:4])%*%alphas)))
for(i in 1:ntel){
ytel[i,] <- rmultinom(1,nfixes,lam[i,]/sum(lam[i,]))
}
Specify starting values and call mle2 function:
start1 <- list(alpha0=alpha0,sigma=sigma,alphas=alphas,betas=betas,n0=log(N-nrow(yscr)))
parnames(CSCR.RSF.intlik2.EXAMPLE) <- names(start)
out1 <- mle2(CSCR.RSF.intlik2.EXAMPLE,start=start1,method="SANN",optimizer="optim",
data=list(yscr=yscr,K=K,X=X,trapcovs=trapcovs,Gden=dencovs[,1:2],Gdet=detcovs[,1:2],
ytel=ytel,stel=stel,dencovs=as.matrix(dencovs[,3:4]),detcovs=as.matrix(detcovs[,3:4]))
)

Resources