8
$\begingroup$

Let's say I have the following data and am running a regression model:

df=data.frame(income=c(5,3,47,8,6,5),
              won=c(0,0,1,1,1,0),
              age=c(18,18,23,50,19,39),
              home=c(0,0,1,0,0,1))

On one hand, I run a linear model to predict on income:

md1 = lm(income ~ age + home + home, data=df)

Second, I run a logit model to predict on the won variable:

md2 = glm(factor(won) ~ age + home, data=df, family=binomial(link="logit"))

For both models, I wonder how I can generate a table or data frame with the predictor response category, fitted value, and the model predicted value.

So for the linear model, something like:

age  fitted_income  predicted_income
18    3              5 
23    3              3
50    4              2
19    5              5
39    6              4

home   fitted_income    predicted_income
0       5               6       
1       3               9

Or perhaps it should be for each data point. So for x_i data point, the fitted and predicted values are:

id   age  fitted_income  predicted_income
1     18    3              5 
2     23    3              3
3     50    4              2
4     19    5              5
5     39    6              4
  1. From a statistical standpoint, is such an undertaking useful? Why or why not?

  2. How can this be done in R? (looked at names(md1) and found what I can pull from the model, but haven't proceeded past that)

Thanks!

$\endgroup$
  • 1
    $\begingroup$ Re #2: stat.ethz.ch/R-manual/R-patched/library/stats/html/…. Re #1: useful for what? What do you want to accomplish in the end? $\endgroup$ – whuber Aug 10 '12 at 17:22
  • $\begingroup$ Useful for telling if the model is "predictive" for each individual data point. I want to look at any row/id, and be able to compare the true/fitted value and the predicted value in order to see how "correct" it is. $\endgroup$ – ATMathew Aug 10 '12 at 17:25
  • $\begingroup$ If you want to scan the table to see how the actual response varies with respect to the covariate I suppose it could be useful. I don't understand your terminology though. the fitted value and the predicted value should be the same. What should differ is the observed value and the fitted value. $\endgroup$ – Michael Chernick Aug 10 '12 at 17:30
  • 2
    $\begingroup$ Could try something like: x=cbind(df,md1$fitted.values) colnames(x)=c(colnames(df),"predicted") $\endgroup$ – RioRaider Aug 10 '12 at 17:33
  • 2
    $\begingroup$ The differences between observed and fitted values are available through the residuals command in R. Use cbind to join them to the original dataframe. $\endgroup$ – whuber Aug 10 '12 at 17:35
18
$\begingroup$

You have to be a bit careful with model objects in R. For example, whilst the fitted values and the predictions of the training data should be the same in the glm() model case, they are not the same when you use the correct extractor functions:

R> fitted(md2)
        1         2         3         4         5         6 
0.4208590 0.4208590 0.4193888 0.7274819 0.4308001 0.5806112 
R> predict(md2)
         1          2          3          4          5          6 
-0.3192480 -0.3192480 -0.3252830  0.9818840 -0.2785876  0.3252830

That is because the default for predict.glm() is to return predictions on the scale of the linear predictor. To get the fitted values we want to apply the inverse of the link function to those values. fitted() does that for us, and we can get the correct values using predict() as well:

R> predict(md2, type = "response")
        1         2         3         4         5         6 
0.4208590 0.4208590 0.4193888 0.7274819 0.4308001 0.5806112

Likewise with residuals() (or resid()); the values stored in md2$residuals are the working residuals are are unlikely to be what you want. The resid() method allows you to specify the type of residual you want and has a useful default.

For the glm() model, something like this will suffice:

R> data.frame(Age = df$age, Won = df$won, Fitted = fitted(md2))
  Age Won    Fitted
1  18   0 0.4208590
2  18   0 0.4208590
3  23   1 0.4193888
4  50   1 0.7274819
5  19   1 0.4308001
6  39   0 0.5806112

Something similar can be done for the lm() model:

R> data.frame(Age = df$age, Income = df$income, Fitted = fitted(md1))
  Age Income    Fitted
1  18      5  7.893273
2  18      3  7.893273
3  23     47 28.320749
4  50      8 -1.389725
5  19      6  7.603179
6  39      5 23.679251
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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