# Visualize effects of a regression with categorical explanatory variables (3 levels) in R?

Using R, I want to run a linear regression to estimate the abnormal return on days with positive, negative and neutral news (CLASS). I'm a beginner in R, as well as in using regression models! First of all the data structure is as follows. CONTROLVAR just represents all the columns I use as control variables.

DATE <- c("1","2","3","4","5","6","7","1","2","3","4","5","6","7")
COMP <- c("A", "A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "B", "B")
RET <- c(-2.0,1.1,3,1.4,-0.2, 0.6, 0.1, -0.21, -1.2, 0.9, 0.3, -0.1,0.3,-0.12)
CLASS <- c("positive", "negative", "aneutral", "positive", "positive", "negative", "aneutral", "positive", "negative", "negative", "positive", "aneutral", "aneutral", "aneutral")
LITIGATION <- c(1,0,0,0,0,0,0,0,0,0,0,0,0,0)
POLLUTION  <- c(1,0,1,1,0,0,0,0,1,0,0,0,0,0)
LAYOFF     <- c(0,1,0,0,0,0,0,0,0,0,0,0,0,0)
CONTROLVAR <- c("11","13","13","14","13","14","12","11","13","13","14","13","14","12")

mydf <- data.frame(DATE, COMP, RET, CLASS, LITIGATION, POLLUTION, LAYOFF, CONTROLVAR, stringsAsFactors=F)

mydf

#    DATE COMP   RET    CLASS LITIGATION POLLUTION LAYOFF CONTROLVAR
# 1     1    A -2.00 positive          1         1      0         11
# 2     2    A  1.10 negative          0         0      1         13
# 3     3    A  3.00 aneutral          0         1      0         13
# 4     4    A  1.40 positive          0         1      0         14
# 5     5    A -0.20 positive          0         0      0         13
# 6     6    A  0.60 negative          0         0      0         14
# 7     7    A  0.10 aneutral          0         0      0         12
# 8     1    B -0.21 positive          0         0      0         11
# 9     2    B -1.20 negative          0         1      0         13
# 10    3    B  0.90 negative          0         0      0         13
# 11    4    B  0.30 positive          0         0      0         14
# 12    5    B -0.10 aneutral          0         0      0         13
# 13    6    B  0.30 aneutral          0         0      0         14
# 14    7    B -0.12 aneutral          0         0      0         12


aneutral (neutral) will be the reference category. I would also like to see the effect of certain subjects of the article on the abnormal return.

I'd like to include interaction, so my model looks like this:

mymodel <- lm(RET ~ CLASS * (LITIGATION + POLLUTION + LAYOFF)   # Interaction Variables
+ CONTROLVAR,     # Control Variables
data=mydf)


Now I don't really understand how to interpret the coefficients I get and I would like to plot a regression line or anything that visualizes these effects to better understand the results. What's a good way of doing this for a three-class-problem like this? abline() doesn't seem to work, because there are too many variables.

Thank you!

• Yet, you do not have enought variability in the Ligitation and Layoff variables to estimate their effects. Unless you provided only a subset of your data? Jun 24 '14 at 17:08
• @ Aurelie: Yes it's just an example data.frame. My original data consists of ~30'000 rows of very similar structure. Couldn't figure out how to get rid of the NA values. Do the NA's cause problems when plotting?
– cptn
Jun 24 '14 at 19:44
• What is RET? Is it a continuous variable? Jun 24 '14 at 21:53
• @ gung: yes RET is the abnormal return of the company on the event day and is continuous.
– cptn
Jun 25 '14 at 6:37

How about some old-school table showing predicted means? (See below)

Once you have all these data, it's possible to plot them. Use Negative > Neutral > Positive as the x-axis, predicted RET on the y-axis. And experiment different ling layouts:

1. All eight lines: possible if they separate from each other very clearly.
2. Four lines on each graph, two panels: For instance, split the graph by litigation yes/no, then then within each use colors to represent pollution, and line styles to represent layoff.
3. Two lines on each group, four panels: Suitable if your eight lines are really close and messy.
• @ Penguin_Knight: Thank you, Oldschool sounds good:)! Is it possible to create such a table in R and plot it directly as you supposed? Or better to tranfer the results of the R-output into such an Excel-table and plot it there?
– cptn
Jun 25 '14 at 6:42
• I just added the code to create the table you need. NB: if CONTROLVAR are not significant, you can remove them from the model. If they are, you have to add a CONTROLVAR column in the table to make the predictions. Jun 26 '14 at 10:58
• In regards to the table, the stop light color scheme is awful for everything besides stoplights - many people are red-green color blind and yellow rarely prints well. Also you could easily round the decimals in your example to the tenths. Some of the numbers have gone an unfortunate rounding, producing a bit of a lie factor when simply scanning the columns as they are right aligned. Jun 26 '14 at 11:33
• Thanks @Andy. I admit that it was a hasty draft. I've replaced the table. Jun 26 '14 at 12:25
• @Aurelie, I don't think Andy has edited the answer. My guess is your reputation is not high enough to edit other's answer? I am not sure. Feel free to post your code as a new answer. Jun 26 '14 at 12:42

Ok, my input in Penguin_Knight post was deleted... I do not know why.

To make the table you need, you have to create a new dataset with all possible combinations of the explanatory variables and then use the predict function to get the predicted means. You can use this code:

LITIGATION <- rep(c(rep(0, 4),rep(1, 4)), 3)
POLLUTION  <- rep(c(rep(0, 2),rep(1, 2)), 6)
LAYOFF     <- rep(c(0,1), 12)
CLASS <- c(rep("Positive", 8),rep("Neutral", 8),rep("Negative", 8))

newdata1 <- data.frame(LITIGATION, POLLUTION, LAYOFF, CLASS)
newdata1$MEANPRED <- predict(mymodel, newdata=newdata1, type="response")  But as I said in my comment, you have to remove the CONTROLVAR variable from the model if it is not significant, or add a new (CONTROLVAR) column to newdata1 to account for it. • I rejected your edit request to Penguin_Knight's post (as did one other before me). This is fine as a separate answer - I didn't see a reason to alter Penguin_Knight's post so substantially. I'm confused by your advice about removing CONTROLVAR - do you mind elaborating? Jun 26 '14 at 13:16 • Ok... I would have had to write everything again if I had closed my R console. I would not have done it I do not have this time. I edited Penguin's answer because my input was complementary (this is why there is an edit function, to improve answers and make them comprehensive...). Jun 26 '14 at 13:46 • I cannot run the model to see whether your CONTROLVAR are significant or not. In order to use the predict function, you need to have a column in newdata1 for every explanatory variables involved in the model. So if these control variables are not significant, the simpler solution is to remove them for the model and run the code I gave. If these control variables are significant however, you have to elaborate a more complex newdata1 table with more columns giving the control variables values. Jun 26 '14 at 13:47 • As far as edits you can go and see the proposed at the link I provided, so they are not lost. The CONTROLVAR's may not be significant in the model because of a high variance, so I wouldn't drop them from the predictions - but I understand your code snippet can not see them. Jun 26 '14 at 14:38 • Ok, noticed, i will know the next time. Jun 26 '14 at 14:45 Another possible solution to make a table with predicted means (independently of whether CONTROLVAR are significant or not): mydf$PRED <- predict(mymodel, newdata=mydf, type="response")
mydf$EXPLCATEGORIES <- paste(mydf$LITTIGATION, mydf$POLLUTION, mydf$LAYOFF, mydf$CLASS) PredictedMeans <- tapply(mydf, mydf$EXPLCATEGORIES, mean)
PredictedMeans\$Categories <- row.names(PredictedMeans)
plot(PredictedMeans[,1]~PredictedMeans[,2])


However, in that case you can only make a plot with all subcategories listed on the x axis, not a well arranged plot were bars are grouped according to variables.