# Which is correct way for regression line?

I have a set of data (some Frequencies per month, Var1 is the month):

> head(dframe)
Var1  Freq
1 34968
2 21151
3 21989
4 23847
5 23351
6 22551


What is the difference of creating the regression line like:

model <- lm(as.numeric(dframe$Freq)~as.numeric(dframe$Var1))


and

lreg <- line(dframe$Freq)  which gives different intercept and slope. line() seems to be less sensitive to outliers. • It seems like you have a question about statistical methodologies rather than a specific programming question. As such, your question is a better fit for Cross Validated. But basically the two methods are complexly different. lm() does a least-squares regression fit and line() does a Tukey "robust" line fit which basically divides the data and does a regression on the medians of the different groups. See the reference in the ?line help page. – MrFlick Oct 23, 2014 at 20:02 • I believe the question is not "which is correct way for regression line?," since the OLS technique has well-known properties. Could you please clarify what you want to do with your data? – chl Oct 23, 2014 at 20:37 • Thank you for taking the time to answer my question. I wanted to build a regression line (for prediction purposes). I did a graphical representation and it seems to me that line was a better approximation of historical data. But your answer helped me, thank you. Sorry for posting in the wrong section. Oct 23, 2014 at 20:55 • @user59196 You will probably have to merge your accounts by following instructions available in our Help Center. – chl Oct 23, 2014 at 21:04 ## 3 Answers The help on lm and line (?lm and ?line) explain what they are. In R, lm fits the least squares regression line. Its description says: ‘lm’ is used to fit linear models. It can be used to carry out regression, single stratum analysis of variance and analysis of covariance ... If you want "the regression line" without any other qualification, use lm, since that's what people almost always mean when they say "the regression line". Now the description for line says: Fit a line robustly as recommended in Exploratory Data Analysis. For further details, you'd consult the book. Tukey is probably best known for the median-median resistant line (sometimes called the three-group line, which is what I generally end up calling it), and I imagine that's probably the one intended -- but to be frank, I think whatever the implementation of line is intended to be, it must be faulty:  line(1:9,1:9) Call: line(1:9, 1:9) Coefficients: [1] -1.0 1.2  That's certainly not the three-group line! Nor is it any other sensible line. Looks like a bug to me. For completeness I'll describe how the three-group (median-median) line is most often described 1. Split the data into three groups of as near to equal size as possible. If the sample size isn't a multiple of three, the middle group has one extra or one fewer points. 2. find the median of x and the median of y for the lower group$(\stackrel{\sim}{x}_L,\stackrel{\sim}{y}_L)$, the middle group$(\stackrel{\sim}{x}_M,\stackrel{\sim}{y}_M)$and the upper group$(\stackrel{\sim}{x}_U,\stackrel{\sim}{y}_U)$. 3. Find the line joining the two outer median-points; this gives the slope, but we need to incorporate information from the center group to help with the intercept. A commonly used version moves the line up or down$\frac{1}{3}$of the way toward the middle point. I think the version in EDA may just use the median residual from$y-\text{slope} \times x$for the intercept, but the move-by-1/3 version -- i.e. the mean of the residuals from the three group-medians - is fast and seems to be widely used for hand calculation without hurting the breakdown point. As you can see, if you apply that algorithm for (1:9,1:9), we ought to get slope 1 intercept 0 (it's also the only reasonable line for that data). If R's line is meant to be the line I just described, it's wrong. [This should be fixed soon, presumably in the next release; a patch was submitted for it, which was mentioned on R-devel mailing list (from the look of it, within a day or so of the 3.4.1 release). Edit: it was not fixed in the 3.4.2 release but it is definitely in the 3.5.0-devel code -- the code for line.c is definitely updated, and I just tried the windows binary, line ran fine on obvious tests like the ones above.] • +1 Very nice analysis. Although line is implemented in C, the nature of its bug becomes clear with a plot to study your example, as in x <- 3:35; sapply(x, function(n) line(1:n, 1:n)$coefficients[2]); plot(x,y). It has severe problems when $n \mod 6 \in\{2,3\}$, decreasing in magnitude with larger $n$. The period $6$ suggests a division into three groups and further subdivision into two groups each (naturally). Look for bad formulas involving int in the C code.
– whuber
Oct 24, 2014 at 16:20

@Glen_b has made some good points. Let me just state that I think neither is a reasonable thing to do. If you look at your data (I added a plot with the two lines overlaid for you), you can see that both look terrible. In addition, if we think about the nature of your situation, we see two issues. First of all, you have a time series, so the data are not independent and you should be skeptical of any standard line fitting technique that does not take the non-independence into account. Second, your data are counts, so you should be wary of methods based on the idea of normal distributions. If you wanted to look at drawing some lines for purely exploratory purposes, I might try lowess with different spans (although for even that to be useful, you will need more than 6 data--your use of head() suggests to me that you do).

I recently had a chance to learn about Tukey resistant line, and here I got the similar curiosity where that line function came from. I also had a doubt that line function has some error during solving homework, I browsed here and there seeking for the answer. I end up here finding out that my suspicion was correct, thanks for simple, correct counterex by @Glen_b. Here I made a simple r_function by myself, and I want to share with Cross Validated since I'm having a lot of help from this site.

res.line=function(x,y){
n=length(x)
qwer=matrix(0,n,2) # creating a matrix in order to arrange x_i,y_i in a same row
for(i in 1:n){
qwer[i,1]=x[i]
qwer[i,2]=y[i]
}
qwer1=qwer[order(x),] # sorting x for the case when the x is not in increasing order
x1=qwer1[,1]
y1=qwer1[,2]

xleftgroup=c(); xmidgroup=c(); xrightgroup=c()
yleftgroup=c(); ymidgroup=c(); yrightgroup=c()
asdf=n%/%3 # quotient of dividing (sample size n) by 3
if(n%%3==0){xleftgroup=x1[1:asdf]; xmidgroup=x1[(asdf+1):(2*asdf)]; xrightgroup=x1[(2*asdf+1):(3*asdf)]}
if(n%%3==0){yleftgroup=y1[1:asdf]; ymidgroup=y1[(asdf+1):(2*asdf)]; yrightgroup=y1[(2*asdf+1):(3*asdf)]}
if(n%%3==1){xleftgroup=x1[1:asdf]; xmidgroup=x1[(asdf+1):(2*asdf+1)]; xrightgroup=x1[(2*asdf+2):n]}
if(n%%3==1){yleftgroup=y1[1:asdf]; ymidgroup=y1[(asdf+1):(2*asdf+1)]; yrightgroup=y1[(2*asdf+2):n]}
if(n%%3==2){xleftgroup=x1[1:(asdf+1)]; xmidgroup=x1[(asdf+2):(2*asdf+1)]; xrightgroup=x1[(2*asdf+2):n]}
if(n%%3==2){yleftgroup=y1[1:(asdf+1)]; ymidgroup=y1[(asdf+2):(2*asdf+1)]; yrightgroup=y1[(2*asdf+2):n]}
# partioning the case when n=3k, n=3k+1, n=3k+2

xl=median(xleftgroup); xm=median(xmidgroup); xr=median(xrightgroup) # x_median after the task is done
yl=median(yleftgroup); ym=median(ymidgroup); yr=median(yrightgroup) # y_median after the task is done
b=(yr-yl)/(xr-xl) # slope
a=(1/3)*( (yl-b*xl)+(ym-b*xm)+(yr-b*xr) ) # intercept
print(c(a,b)) # printing slope and intercept
}


This is it. Um, Unlike linefunction, it doesn't have coef, residuals, fitted. So every single time you need to designate it by yourself. I would be happy if I could also code that, but sorry that I can't. Hope someone could do it.

Anyway, I'm leaving this answer for someone who would having trouble after finding out that line function is wrong. Thanks.