I'm currently working with a dataset in R and my $B_0$ result is different when I run linear regression with & without converting the data into factors. And I want to understand what I'm doing wrong here.

# IV: Time
time = c(-1, -1, -1, 0, 0, 0, 1, 1, 1)
time.f = factor(time, levels=c(-1, 0, 1), labels=c("low", "med", "high"))
# IV: Temp
temp = c(-1, 0, 1, -1, 0, 1, -1, 0, 1)
temp.f = factor(temp, levels=c(-1, 0, 1), labels=c("low", "med", "high"))
# IV: Acid
acid = c(-1, 0, 1, 1, -1, 0, 0, 1, -1)
acid.f = factor(acid, levels=c(-1, 0, 1), labels=c("low", "med", "high"))
# DV: Uranium Recovery (%)
urecovery = c(86.88, 88.96, 93.68, 88.92, 86.96, 91.26, 88.20, 93.20, 88.75)

# Combine into data frame
x = cbind(time, temp, acid)
x_factors = cbind(time.f, temp.f, acid.f)

data1 = data.frame(cbind(urecovery, x))
data2 = data.frame(cbind(urecovery, x_factors))

# Least Squares
u = lm(urecovery ~ time + temp + acid, data=data1)

u2 = lm(urecovery ~ time.f + temp.f + acid.f, data=data2)

Could someone explain why only the $B_0$ is different, I think I'm most likely setting up the factor part wrong.


2 Answers 2


1) If your code did what you wanted, then this would be the problem:

When a -1/0/1 variable is used directly in a linear regression, you're regressing on its actual values.

As a result, the model you're fitting when you do that stipulates that the effect of going from -1 to 0 is the same as the effect of going from 0 to 1, and the effect of going from -1 to 1 is therefore twice either of the other effects. (You're treating that variable as interval and the response is linear in that variable.)

When you fit the variable as a factor, the three values are simply labels. The effect of going from category "-1" to category "0" needn't even have the same sign as going from category "0" to "1".

In the first case you have a single predictor; in the second, you have an additional predictor which corresponds to picking up the nonlinearity in the relationship, if any.

As a result, there's no reason to expect the intercept to be the same (in fact, you can show that it generally won't be the same).

2) Your code doesn't do what you want!

> is.factor(time.f)
[1] TRUE
> is.factor(data2$time.f)

> table(time.f)
 low  med high 
   3    3    3 
> table(data2$time.f)

1 2 3 
3 3 3 

Your factor has simply been turned back into another numeric (interval) variable, but with a shifted origin. Which is why the intercept is different in this case.

x_factors = cbind(time.f, temp.f, acid.f)
data2 = data.frame(cbind(urecovery, x_factors))

These lines seems to be the problem. When you cbind different factors together, they become coerced into a numeric matrix. So what ends up happening is that data2 is the same as data (the independent variables are numeric), but the values are now {1, 2, 3} instead of {-1, 0, 1} due to the prior conversion to a factor. (That's just how R converts a factor into numeric – levels get assigned to numbers 1 through k.)

You can check this by using summary() or str() on the x_factors or data2 variables.

Thus, your lm results are the same, except for a different intercept, because {1, 2, 3} has the same numeric effect as {-1, 0, 1}, but now you have a different mean value.

If you want to actually treat the independent variables as factors, I recommend constructing your data.frame by either specifying each variable separately:

data3 <- data.frame(urecovery, time.f, temp.f, acid.f)

or converting variables to factors after combining together:

data4 <- data2
data4$time.f <- as.factor(data4$time.f)
data4$temp.f <- as.factor(data4$temp.f)
data4$acid.f <- as.factor(data4$acid.f)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.