Constrained linear regression in R

jpkelley

TS Contributor
#1
Hi all,
Using R, I'm running a linear regression for part of a function I'm writing to calculate survival rates from age distributions. My question for the purpose of this thread is following. Given the following sample data set:

Code:
set.seed(100)
fake.data <- data.frame(x=seq(1:20), y=rnorm(20, 10,2)*rev(seq(1:20)))
...how can one constrain the least-squares regression to be anchored at a given point on the y axis (e.g. 170? What I am NOT looking for is a simple shift in the intercept. That is, a solution would give different beta coefficients for a regular regression and the regression model constrained to run through (0,170). In this example, only the intercept is constrained while slope can vary. I'm mentally fried right now, but I imagine there's a very simple solution to this using lme() in package "nlme."

Attached is an image illustrating the slopes of constrained and unconstrained slopes (please forgive spelling error in legend):
View attachment 1459

Any ideas about this, right off the tops of those heads of yours?
 
Last edited:

jpkelley

TS Contributor
#2
I may have found a solution. Stupid me, forgetting my simple math of putting a line through a point. If I get it, I'll post the answer. Still open to simple suggestions, however.
 

jpkelley

TS Contributor
#3
OK, much simpler than I thought.

The solution in R is something like the following, with code elaborated to make it a bit more transparent:
Code:
newy <- y-max(y)   # This scales the y to y=0 (the origin)
newx <- x- min(x)    # This scale the x to x=0 (the origin)

# Then, you simply force the regression through the origin by excluding a random intercept:
lm(newy ~ newy)
Since I am only needed the slope, I do not need to shift the axes. Anyway, that's the solution in case anyone is curious.
 

bryangoodrich

Probably A Mammal
#4
If you don't have interest in saving the modified data sets, you can create them inline for lm:

Code:
lm(newy ~ newx, data = transform(df, newy = y - max(y), newx = x - min(x))) ## df is original data frame
 

bryangoodrich

Probably A Mammal
#7
Much, much better. I don't know why I don't use transform(). Amateur hour on my part! This helps quite a bit.
I also didn't even know about transform until the past several months when I started taking reading about R seriously. There's also a "within" function that I've used once because of the way it handles scope and did what I wanted it to do (and transform didn't work). The thing I like about transform is how it handles scope--viz., you're given access to everything within the scope of what is being transformed like using with. It makes for convenient data manipulations. Before I was using data.frame or cbind or something like that, sometimes with with; very inefficient!