Plot lqmm functions - r
I am struggling to find examples online as to how lqmm models can be easily plotted. So for example, below, I would like a simple plot where I can predict multiple quantiles and overlay these predictions onto a scatterplot:
library(lqmm)
set.seed(123)
M <- 50
n <- 10
test <- data.frame(x = runif(n*M,0,1), group = rep(1:M,each=n))
test$y <- 10*test$x + rep(rnorm(M, 0, 2), each = n) + rchisq(n*M, 3)
fit.lqm <- lqm(y ~ x , tau=c(0.1,0.5,0.9),data = test)
fit.lqmm <- lqmm(fixed = y ~ x, random = ~ 1, group = group, data = test, tau = 0.5, nK = 11, type = "normal")
I can do this successfully for lqm models, but not lqmm models.
plot(y~x,data=test)
for (k in 1:3){
curve((coef.lqm(fit.lqm)[1,k])+(coef.lqm(fit.lqm)[2,k])*(x), add = TRUE)
}
I have seen the predict.lqmm function, but this returns the predicted value for each x-value in the dataset, rather than a smooth function over the x-axis limit. Thank you in advance for any help.
You get only a single vector for coef.lqmm so you can draw a line with the values:
coef(fit.lqmm)
#(Intercept) x
# 3.443475 9.258331
plot(y~x,data=test)
curve( coef(fit.lqmm)[1] +coef(fit.lqmm)[2]*(x), add = TRUE)
To get the quantile equivalent of normal theory confidence intervals you need to supply tau-vectors. This is for a 90% coverage estimate:
fit.lqmm <- lqmm(fixed = y ~ x, random = ~ 1, group = group, data = test, tau = c(0.05, 0.5, 0.95), nK = 11, type = "normal")
pred.lqmm <- predict(fit.lqmm, level = 1)
str(pred.lqmm)
num [1:500, 1:3] 2.01 7.09 3.24 8.05 8.64 ...
- attr(*, "dimnames")=List of 2
..$ : chr [1:500] "1" "2" "3" "4" ...
..$ : chr [1:3] "0.05" "0.50" "0.95"
coef(fit.lqmm)
0.05 0.50 0.95
(Intercept) 0.6203104 3.443475 8.192738
x 10.1502027 9.258331 8.620478
plot(y~x,data=test)
for (k in 1:3){
curve((coef.lqmm(fit.lqmm) [1,k])+(coef.lqmm(fit.lqmm) [2,k])*(x), add = TRUE)
}
Related
How to select appropriate sin() terms to fit a time series using R
I want to fit a time series with sin() function because it has a form of some periods (crests and troughs). However, for now I only guessed it, e.g., 1 month, two months, ..., 1 year, 2 year. Is there some function in R to estimate the multiple periods in a data series? Below is an example which I want to fit it using the combination of sin() functions. The expression in lm() is a try after several guesses (red line in the Figure below). How can I find the sin() terms with appropriate periods? t <- 1:365 y <- c(-1,-1.3,-1.6,-1.8,-2.1,-2.3,-2.5,-2.7,-2.9,-3,-2,-1.1,-0.3,0.5,1.1,1.6,2.1,2.5,2.8,3.1,3.4,3.7,4.2,4.6,5,5.3,5.7,5.9,6.2,5.8,5.4,5,4.6,4.2,3.9,3.6,3.4,3.1,2.9,2.8,2.6,2.5,2.3,1.9,1.5,1.1,0.8,0.5,0.2,0,-0.1,-0.3,-0.4,-0.5,-0.5,-0.6,-0.7,-0.8,-0.9,-0.8,-0.6,-0.3,-0.1,0.1,0.4,0.6,0.9,1.1,1.3,1.5,1.7,2.1,2.4,2.7,3,3.3,3.5,3.8,4.3,4.7,5.1,5.5,5.9,6.2,6.4,6.6,6.7,6.8,6.8,6.9,7,6.9,6.8,6.7, 6.5,6.4,6.4,6.3,6.2,6,5.9,5.7,5.6,5.5,5.4,5.4,5.1,4.9,4.8,4.6,4.5,4.4,4.3,3.9,3.6,3.3,3,2.8,2.6,2.4,2.6,2.5,2.4,2.3,2.3,2.2,2.2,2.3,2.4,2.4,2.5,2.5,2.6,2.6,2.4,2.1,1.9,1.8,1.6,1.4,1.3,1,0.7,0.5,0.2,0,-0.2,-0.4,-0.2,-0.1,0.1,0.1,0.1,0.1,0.1,0.1,0,0,-0.1,-0.1,-0.2,-0.2,-0.3,-0.3,-0.4,-0.5,-0.5,-0.6,-0.7,-0.7,-0.8,-0.8,-0.8,-0.9,-0.9,-0.9,-1.3,-1.6,-1.9,-2.1,-2.3,-2.6,-2.9,-2.9,-2.9,-2.9, -2.9,-3,-3,-3,-2.8,-2.7,-2.5,-2.4,-2.3,-2.2,-2.1,-2,-2,-1.9,-1.9,-1.8,-1.8,-1.8,-1.9,-1.9,-2,-2.1,-2.2,-2.2,-2.3,-2.4,-2.5,-2.6,-2.7,-2.8,-2.9,-2.9,-2.9,-2.9,-2.9,-2.9,-2.9,-2.9,-2.9,-2.9,-2.8,-2.8,-2.7,-2.7,-2.6,-2.6,-2.8,-3,-3.1,-3.3,-3.4,-3.5,-3.6,-3.5,-3.4,-3.3,-3.3,-3.2,-3,-2.9,-2.8,-2.8,-2.7,-2.6,-2.6,-2.6,-2.5,-2.6,-2.7,-2.8,-2.8,-2.9,-3,-3,-3,-3,-2.9,-2.9,-2.9,-2.9,-2.9,-2.8, -2.7,-2.6,-2.5,-2.4,-2.3,-2.3,-2.1,-1.9,-1.8,-1.7,-1.5,-1.4,-1.3,-1.5,-1.7,-1.8,-1.9,-2,-2.1,-2.2,-2.4,-2.5,-2.6,-2.7,-2.8,-2.8,-2.9,-3.1,-3.2,-3.3,-3.4,-3.5,-3.5,-3.6,-3.6,-3.5,-3.4,-3.3,-3.2,-3.1,-3,-2.7,-2.3,-2,-1.8,-1.5,-1.3,-1.1,-0.9,-0.7,-0.6,-0.5,-0.3,-0.2,-0.1,-0.3,-0.5,-0.6,-0.7,-0.8,-0.9,-1,-1.1,-1.1,-1.2,-1.2,-1.2,-1.2,-1.2,-0.8,-0.4,-0.1,0.2,0.5,0.8,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.6,0.3,0,-0.2,-0.5,-0.7,-0.8) dt <- data.frame(t = t, y = y) plot(x = dt$t, y = dt$y) lm <- lm(y ~ sin(2*3.1416/365*t)+cos(2*3.1416/365*t)+ sin(2*2*3.1416/365*t)+cos(2*2*3.1416/365*t)+ sin(2*4*3.1416/365*t)+cos(2*4*3.1416/365*t)+ sin(2*5*3.1416/365*t)+cos(2*5*3.1416/365*t)+ sin(2*6*3.1416/365*t)+cos(2*6*3.1416/365*t)+ sin(2*0.5*3.1416/365*t)+cos(2*0.5*3.1416/365*t), data = dt) summary(lm)$adj.r.squared plot(dt$y); lines(predict(lm), type = "l", col = "red")
Package forecast has the fourier function (see here), which allows you to model fourier series terms based on time series objects. For example: library(forecast) dt$y <- ts(dt$y, frequency = 365) lm<- lm(y ~ fourier(y, K=6), dt) plot(dt$t, dt$y); lines(predict(lm), type = "l", col = "red")
Following my comment to the question, In catastrophic-failure's answer replace Mod by Re as in SleuthEye's answer. Then call nff(y, 20, col = "red"). I realized that there is another correction to function nff to be made: substitute length(x) or xlen for the magical number 73. Here is the function corrected. nff = function(x = NULL, n = NULL, up = 10L, plot = TRUE, add = FALSE, main = NULL, ...){ #The direct transformation #The first frequency is DC, the rest are duplicated dff = fft(x) #The time xlen <- length(x) t = seq_along(x) #Upsampled time nt = seq(from = 1L, to = xlen + 1L - 1/up, by = 1/up) #New spectrum ndff = array(data = 0, dim = c(length(nt), 1L)) ndff[1] = dff[1] #Always, it's the DC component if(n != 0){ ndff[2:(n+1)] <- dff[2:(n+1)] #The positive frequencies always come first #The negative ones are trickier ndff[(length(ndff) - n + 1):length(ndff)] <- dff[(xlen - n + 1L):xlen] } #The inverses indff = fft(ndff/xlen, inverse = TRUE) idff = fft(dff/xlen, inverse = TRUE) if(plot){ if(!add){ plot(x = t, y = x, pch = 16L, xlab = "Time", ylab = "Measurement", main = ifelse(is.null(main), paste(n, "harmonics"), main)) lines(y = Re(idff), x = t, col = adjustcolor(1L, alpha = 0.5)) } lines(y = Re(indff), x = nt, ...) } ret = data.frame(time = nt, y = Mod(indff)) return(ret) } y <- c(-1,-1.3,-1.6,-1.8,-2.1,-2.3,-2.5,-2.7,-2.9,-3,-2,-1.1,-0.3,0.5,1.1,1.6,2.1,2.5,2.8,3.1,3.4,3.7,4.2,4.6,5,5.3,5.7,5.9,6.2,5.8,5.4,5,4.6,4.2,3.9,3.6,3.4,3.1,2.9,2.8,2.6,2.5,2.3,1.9,1.5,1.1,0.8,0.5,0.2,0,-0.1,-0.3,-0.4,-0.5,-0.5,-0.6,-0.7,-0.8,-0.9,-0.8,-0.6,-0.3,-0.1,0.1,0.4,0.6,0.9,1.1,1.3,1.5,1.7,2.1,2.4,2.7,3,3.3,3.5,3.8,4.3,4.7,5.1,5.5,5.9,6.2,6.4,6.6,6.7,6.8,6.8,6.9,7,6.9,6.8,6.7, 6.5,6.4,6.4,6.3,6.2,6,5.9,5.7,5.6,5.5,5.4,5.4,5.1,4.9,4.8,4.6,4.5,4.4,4.3,3.9,3.6,3.3,3,2.8,2.6,2.4,2.6,2.5,2.4,2.3,2.3,2.2,2.2,2.3,2.4,2.4,2.5,2.5,2.6,2.6,2.4,2.1,1.9,1.8,1.6,1.4,1.3,1,0.7,0.5,0.2,0,-0.2,-0.4,-0.2,-0.1,0.1,0.1,0.1,0.1,0.1,0.1,0,0,-0.1,-0.1,-0.2,-0.2,-0.3,-0.3,-0.4,-0.5,-0.5,-0.6,-0.7,-0.7,-0.8,-0.8,-0.8,-0.9,-0.9,-0.9,-1.3,-1.6,-1.9,-2.1,-2.3,-2.6,-2.9,-2.9,-2.9,-2.9, -2.9,-3,-3,-3,-2.8,-2.7,-2.5,-2.4,-2.3,-2.2,-2.1,-2,-2,-1.9,-1.9,-1.8,-1.8,-1.8,-1.9,-1.9,-2,-2.1,-2.2,-2.2,-2.3,-2.4,-2.5,-2.6,-2.7,-2.8,-2.9,-2.9,-2.9,-2.9,-2.9,-2.9,-2.9,-2.9,-2.9,-2.9,-2.8,-2.8,-2.7,-2.7,-2.6,-2.6,-2.8,-3,-3.1,-3.3,-3.4,-3.5,-3.6,-3.5,-3.4,-3.3,-3.3,-3.2,-3,-2.9,-2.8,-2.8,-2.7,-2.6,-2.6,-2.6,-2.5,-2.6,-2.7,-2.8,-2.8,-2.9,-3,-3,-3,-3,-2.9,-2.9,-2.9,-2.9,-2.9,-2.8, -2.7,-2.6,-2.5,-2.4,-2.3,-2.3,-2.1,-1.9,-1.8,-1.7,-1.5,-1.4,-1.3,-1.5,-1.7,-1.8,-1.9,-2,-2.1,-2.2,-2.4,-2.5,-2.6,-2.7,-2.8,-2.8,-2.9,-3.1,-3.2,-3.3,-3.4,-3.5,-3.5,-3.6,-3.6,-3.5,-3.4,-3.3,-3.2,-3.1,-3,-2.7,-2.3,-2,-1.8,-1.5,-1.3,-1.1,-0.9,-0.7,-0.6,-0.5,-0.3,-0.2,-0.1,-0.3,-0.5,-0.6,-0.7,-0.8,-0.9,-1,-1.1,-1.1,-1.2,-1.2,-1.2,-1.2,-1.2,-0.8,-0.4,-0.1,0.2,0.5,0.8,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.6,0.3,0,-0.2,-0.5,-0.7,-0.8) res <- nff(y, 20, col = "red") str(res) #> 'data.frame': 3650 obs. of 2 variables: #> $ time: num 1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 ... #> $ y : num 1.27 1.31 1.34 1.37 1.4 ... Created on 2022-10-17 with reprex v2.0.2
The functions sinusoid and mvrm from package BNSP allow one to specify the number of harmonics and if that number is too high, the algorithm can remove some of the unnecessary terms and avoid overfitting. # Specify the model model <- y ~ sinusoid(t, harmonics = 20, amplitude = 1, period = 365) # Fit the model m1 <- mvrm(formula = model, data = dt, sweeps = 5000, burn = 3000, thin = 2, seed = 1, StorageDir = getwd()) # ggplot plotOptionsM <- list(geom_point(data = dt, aes(x = t, y = y))) plot(x = m1, term = 1, plotOptions = plotOptionsM, intercept = TRUE, quantiles = c(0.005, 0.995), grid = 100) In this particular example, among the 20 harmonics, the 19 appear to be important.
How can I perform bootstrap to find the confidence interval for a k-nn model in R?
I have a training df with 2 columns like a b 1 1000 20 2 1008 13 ... n ... ... Now, as I am required to find a 95% CI for the estimate of 'b' based on a specific 'a' value, with a 'k' value of my choice and compare the CI result to other specific value of 'k's. My question is how can I perform bootstrap for this with 1000 bootstrap reps as I am required to use a fitted knn model for the training data with kernel = 'gaussian' and k can only be in range 1-20 ? I have found that the best k for this model is k = 5, and had a go for bootstrap but it doesn't work library(kknn) library(boot) boot.kn = function(formula, data, indices) { # Create a bootstrapped version d = data[indices,] # Fit a model for bs fit.kn = fitted(train.kknn(formula,data, kernel= "gaussian", ks = 5)) # Do I even need this complicated block target = as.character(fit.kn$terms[[2]]) rv = my.pred.stats(fit.kn, d[,target]) return(rv) } bs = boot(data=df, statistic=boot.kn, R=1000, formula=b ~ a) boot.ci(bs,conf=0.95,type="bca") Please inform me for more info if I'm not clear enough. Thank you.
Here is a way to regress b on a with the k-nearest neighbors algorithm. First, a data set. This is a subset of the iris data set, keeping the first two columns. One row is removed to later be the new data. i <- which(iris$Sepal.Length == 5.3) df1 <- iris[-i, 1:2] newdata <- iris[i, 1:2] names(df1) <- c("a", "b") names(newdata) <- c("a", "b") Now load the packages to be used and determine the optimal value for k with package kknn. library(caret) library(kknn) library(boot) fit <- kknn::train.kknn( formula = b ~ a, data = df1, kmax = 15, kernel = "gaussian", distance = 1 ) k <- fit$best.parameters$k k #[1] 9 And bootstrap predictions for the new point a <- 5.3. boot.kn <- function(data, indices, formula, newdata, k){ d <- data[indices, ] fit <- knnreg(formula, data = d) predict(fit, newdata = newdata) } set.seed(2021) R <- 1e4 bs <- boot(df1, boot.kn, R = R, formula = b ~ a, newdata = newdata, k = k) ci <- boot.ci(bs, level = 0.95, type = "bca") ci #BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS #Based on 10000 bootstrap replicates # #CALL : #boot.ci(boot.out = bs, type = "bca", level = 0.95) # #Intervals : #Level BCa #95% ( 3.177, 3.740 ) #Calculations and Intervals on Original Scale Plot the results. old_par <- par(mfrow = c(2, 1), oma = c(5, 4, 0, 0) + 0.1, mar = c(1, 1, 1, 1) + 0.1) hist(bs$t, main = "Histogram of bootstrap values") abline(v = 3.7, col = "red") abline(v = mean(bs$t), col = "blue") abline(v = ci$bca[4:5], col = "blue", lty = "dashed") plot(b ~ a, df1) points(5.3, 3.7, col = "red", pch = 19) points(5.3, mean(bs$t), col = "blue", pch = 19) arrows(x0 = 5.3, y0 = ci$bca[4], x1 = 5.3, y1 = ci$bca[5], col = "blue", angle = 90, code = 3) par(old_par)
simulating a simple linear model
I'm trying to simulate a simple linear model 100 times and find the LS estimation of B1 from the linear model. set.seed(123498) x<-rnorm(z, 0, 1) e<-rnorm(z, 0 ,2) y<-0.5 + 2*x + e model<- lm(y~x) simulaten=100 z=10 for (i in 1:simulaten){ e<-rnorm(n, 0 ,2) x<-rnorm(n, 0, 1) y<-0.5 + 2*x + e model<- lm(y~x)} summary(model) Is that what my for loop is achieving or have i missed the mark?
Here is a replicate solution. I have set n (forgotten in the question) and simulaten to a smaller value. n <- 100 simulaten <- 4 set.seed(123498) model_list <- replicate(simulaten, { e <- rnorm(n, 0, 2) x <- rnorm(n, 0, 1) y <- 0.5 + 2*x + e lm(y ~ x) }, simplify = FALSE) model_list Edit Several statistics can be obtained from the models list. The coefficients are extracted with function coef applied to each model. Done with sapply, the returned object is a 2 rows matrix. betas <- sapply(model_list, coef) str(betas) # num [1:2, 1:1000] 0.671 1.875 0.374 2.019 0.758 ... # - attr(*, "dimnames")=List of 2 # ..$ : chr [1:2] "(Intercept)" "x" # ..$ : NULL As for the graph, here is an example. Note that in order for the x axis to reach all the x values, in the first call to hist argument xlim is set to range(betas). lgd <- c(expression(beta[0]), expression(beta[1])) hist(betas[1, ], freq = FALSE, col = "lightblue", xlim = range(betas), ylim = c(0, 2.5), xlab = "betas", main = "") hist(betas[2, ], freq = FALSE, col = "blue", add = TRUE) legend("top", legend = lgd, fill = c("lightblue", "blue"), horiz = TRUE)
The model is updated in each of the iteration. So the summary is returning the summary output of the last 'model'. We could store it in a list. # // initialize empty list of length equals length of simulaten modellst <- vector('list', simulaten) for(i in seq_len(simulaten)) { e <- rnorm(n, 0 ,2) x <- rnorm(n, 0, 1) y <- 0.5 + 2*x + e # // assign the model output to the corresponding list element modellst[[i]] <- lm(y~x) }
predicting from flexmix object (R)
I fit some data to a mixture distribution of two gaussian in flexmix: data("NPreg", package = "flexmix") mod <- flexmix(yn ~ x, data = NPreg, k = 2, model = list(FLXMRglm(yn ~ x, family= "gaussian"), FLXMRglm(yn ~ x, family = "gaussian"))) the model fit is as follows: > mod Call: flexmix(formula = yn ~ x, data = NPreg, k = 2, model = list(FLXMRglm(yn ~ x, family = "gaussian"), FLXMRglm(yn ~ x, family = "gaussian"))) Cluster sizes: 1 2 74 126 convergence after 31 iterations But how do I actually predict from this model? when I do pred <- predict(mod, NPreg) I get a list with the predictions from each of the two components To get a single prediction, do I have to add in the cluster sizes like this? single <- (74/200)* pred$Comp.1[,1] + (126/200)*pred$Comp.2[,2]
I use flexmix for prediction in the following way: pred = predict(mod, NPreg) clust = clusters(mod,NPreg) result = cbind(NPreg,data.frame(pred),data.frame(clust)) plot(result$yn,col = c("red","blue")[result$clust],pch = 16,ylab = "yn") And the confusion matrix: table(result$class,result$clust) For getting the predicted values of yn, I select the component value of the cluster to which a data point belongs. for(i in 1:nrow(result)){ result$pred_model1[i] = result[,paste0("Comp.",result$clust[i],".1")][i] result$pred_model2[i] = result[,paste0("Comp.",result$clust[i],".2")][i] } The actual vs predicted results show the fit (adding only one of them here as both of your models are same, you would use pred_model2 for the second model). qplot(result$yn, result$pred_model1,xlab="Actual",ylab="Predicted") + geom_abline() RMSE = sqrt(mean((result$yn-result$pred_model1)^2)) gives a root mean square error of 5.54. This answer is based on many SO answers I read through while working with flexmix. It worked well for my problem. You may also be interested in visualizing the two distributions. My model was the following, which shows some overlap as the ratio of components are not close to 1. Call: flexmix(formula = yn ~ x, data = NPreg, k = 2, model = list(FLXMRglm(yn ~ x, family = "gaussian"), FLXMRglm(yn ~ x, family = "gaussian"))) prior size post>0 ratio Comp.1 0.481 102 129 0.791 Comp.2 0.519 98 171 0.573 'log Lik.' -1312.127 (df=13) AIC: 2650.255 BIC: 2693.133 I also generate a density distribution with histograms to visulaize both components. This was inspired by a SO answer from the maintainer of betareg. a = subset(result, clust == 1) b = subset(result, clust == 2) hist(a$yn, col = hcl(0, 50, 80), main = "",xlab = "", freq = FALSE, ylim = c(0,0.06)) hist(b$yn, col = hcl(240, 50, 80), add = TRUE,main = "", xlab = "", freq = FALSE, ylim = c(0,0.06)) ys = seq(0, 50, by = 0.1) lines(ys, dnorm(ys, mean = mean(a$yn), sd = sd(a$yn)), col = hcl(0, 80, 50), lwd = 2) lines(ys, dnorm(ys, mean = mean(b$yn), sd = sd(b$yn)), col = hcl(240, 80, 50), lwd = 2) # Joint Histogram p <- prior(mod) hist(result$yn, freq = FALSE,main = "", xlab = "",ylim = c(0,0.06)) lines(ys, p[1] * dnorm(ys, mean = mean(a$yn), sd = sd(a$yn)) + p[2] * dnorm(ys, mean = mean(b$yn), sd = sd(b$yn)))
You can pass an additional argument to your prediction call. pred <- predict(mod, NPreg, aggregate = TRUE)[[1]][,1]
Why is gradient of first iteration step singular in nls with biv.norm
I am trying to fit a non-linear regression model where the mean-function is the bivariate normal distribution. The parameter to specify is the correlation rho. The problem: "gradient of first iteration step is singular". Why? I have here a little example with simulated data. # given values for independent variables x1 <- c(rep(0.1,5), rep(0.2,5), rep(0.3,5), rep(0.4,5), rep(0.5,5)) x2 <- c(rep(c(0.1,0.2,0.3,0.4,0.5),5)) ## 1 generate values for dependent variable (incl. error term) # from bivariate normal distribution with assumed correlation rho=0.5 fun <- function(b) pmnorm(x = c(qnorm(x1[b]), qnorm(x2[b])), mean = c(0, 0), varcov = matrix(c(1, 0.5, 0.5, 1), nrow = 2)) set.seed(123) y <- sapply(1:25, function(b) fun(b)) + runif(25)/1000 # put it in data frame dat <- data.frame(y=y, x1=x1, x2=x2 ) # 2 : calculate non-linear regression from the generated data # use rho=0.51 as starting value fun <- function(x1, x2,rho) pmnorm(x = c(qnorm(x1), qnorm(x2)), mean = c(0, 0), varcov = matrix(c(1, rho, rho, 1), nrow = 2)) nls(formula= y ~ fun(x1, x2, rho), data= dat, start=list(rho=0.51), lower=0, upper=1, trace=TRUE) This yields an error message: Error in nls(formula = y ~ fun(x1, x2, rho), data = dat, start = list(rho = 0.51), : singulärer Gradient In addition: Warning message: In nls(formula = y ~ fun(x1, x2, rho), data = dat, start = list(rho = 0.51), : Obere oder untere Grenzen ignoriert, wenn nicht algorithm= "port" What I don't understand is I have only one variable (rho), so there is only one gradient which must be =0 if the matrix of gradients is supposed to be singular. So why should the gradient be =0? The start value cannot be the problem as I know the true rho=0.5. So the start value =0.51 should be fine, shouldn't it? The data cannot be completely linear dependent as I added an error term to y. I would appreciate help very much. Thanks already.
Perhaps "optim" does a better job than "nls": library(mnormt) # given values for independent variables x1 <- c(rep(0.1,5), rep(0.2,5), rep(0.3,5), rep(0.4,5), rep(0.5,5)) x2 <- c(rep(c(0.1,0.2,0.3,0.4,0.5),5)) ## 1 generate values for dependent variable (incl. error term) # from bivariate normal distribution with assumed correlation rho=0.5 fun <- function(b) pmnorm(x = c(qnorm(x1[b]), qnorm(x2[b])), mean = c(0, 0), varcov = matrix(c(1, 0.5, 0.5, 1), nrow = 2)) set.seed(123) y <- sapply(1:25, function(b) fun(b)) + runif(25)/1000 # put it in data frame dat <- data.frame(y=y, x1=x1, x2=x2 ) # 2 : calculate non-linear regression from the generated data # use rho=0.51 as starting value fun <- function(x1, x2,rho) pmnorm(x = c(qnorm(x1), qnorm(x2)), mean = c(0, 0), varcov = matrix(c(1, rho, rho, 1), nrow = 2)) f <- function(rho) { sum( sapply( 1:nrow(dat), function(i){ (fun(dat[i,2],dat[i,3],rho) - dat[i,1])^2 } ) ) } optim(0.51, f, method="BFGS") The result is not that bad: > optim(0.51, f, method="BFGS") $par [1] 0.5043406 $value [1] 3.479377e-06 $counts function gradient 14 4 $convergence [1] 0 $message NULL Maybe even a little bit better than 0.5: > f(0.5043406) [1] 3.479377e-06 > f(0.5) [1] 1.103484e-05 > Let's check another start value: > optim(0.8, f, method="BFGS") $par [1] 0.5043407 $value [1] 3.479377e-06 $counts function gradient 28 6 $convergence [1] 0 $message NULL