tags:

views:

542

answers:

2

I have a barplot for which the second half should fit to this formula: y~a*x*exp(-b*x^2). Now I want to plot the entire barplot and display the fitted model over the last part of the barplot as it only holds for that part. However, I cannot find a way to display the line-graph only over the second half. If I just do something like


submitted=c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 2L, 2L, 3L, 2L, 1L, 1L, 4L, 
3L, 2L, 11L, 6L, 2L, 16L, 7L, 17L, 36L, 27L, 39L, 41L, 33L, 42L, 
66L, 92L, 138L, 189L, 249L, 665L, 224L, 309L, 247L, 641L, 777L, 
671L, 532L, 749L, 506L, 315L, 292L, 281L, 130L, 137L, 91L, 40L, 
27L, 34L, 19L, 1L)
x=seq(0:(length(submitted)-1))
y1=rs$submitted[30:(length(submitted)-1)]
x1=seq(0:(length(y1)-1))
fit1=nls(y1~a*x1*exp(-b*x1^2),start=list(a=500,b=.01),trace=TRUE)
barplot(submitted,names.arg=x, las=2, cex.axis=0.8, cex=0.8)
lines(predict(fit1))

The line is displayed, but in the wrong position. So how can I control where the line is drawn?

A: 

Take the answer from Aniko and reshape it to your specific problem. I used the data submitted as you have posted.

Define your variables:

y1 <- submitted[30:(length(submitted)-1)]
x1 <- seq(length(y1))

It is enough just using the seq() function this way. It already does the job for you. Then you do the fit and capture the x-values of your barplot() as mentioned by Aniko. That will save the x-values in a matrix so I use as.vector() afterwards to turn it into a vector and make things a little easier.

fit1 <- nls(y1~a*x1*exp(-b*x1^2),start=list(a=500,b=.01),trace=TRUE)
bar <- barplot(submitted, las=2, cex.axis=0.8, cex=0.8)
bar2 <- as.vector(bar)

If you simply print your bar2 you will see the exact values and now you can specify where to place your fit in the plot. Be sure that in your following lines() function the x-vector is of the same length as the y-vector. Eg you can simply do some additional checks with the length() function. Here is the your fit placed into the second half of your barplot:

lines(x = bar2[30:(length(bar2)-1)], y = predict(fit1))
mropa
+2  A: 

A reproducible example would have been helpful, but probably the issue is that the bars are not located at the x-coordinates that you expect. You can find out the x-coordinates of the bars by capturing the output of the barplot function:

dat <- 1:5                   # fake data for barplot
fit <- dat+rnorm(5, sd=0.1)  # fake fitted values

bp <- barplot(dat)           # draw plot and capture x-coordinates
lines(bp, fit)               # add line

Edit:
The same principle can be used for adding a partial line. Rewriting your code a bit to get an index idx showing the parts of the data that you want to model:

x <- 0:(length(submitted)-1) 
idx <- 30:(length(submitted)-1)  # the part of the data to be modeled
y1 <- submitted[idx] 
x1 <- idx-30 
fit1 <- nls(y1~a*x1*exp(-b*x1^2),start=list(a=500,b=.01),trace=TRUE) 
# capture the midpoints from the barplot
bp <- barplot(submitted,names.arg=x, las=2, cex.axis=0.8, cex=0.8) 
# subset the midpoints to the range of the fit
lines(bp[idx], predict(fit1)) 

(note that I also changed seq(0:n) to 0:n, because the first does not give you a sequence of 0 to n.)

Aniko
I've added some example data to my original post. As you can it differs from you fake data. I hope it helps.
Pieter