Reputation: 29
I am trying to create a coefficient plot using ggplot
that combines the results of two different regressions. The coefficients, standard errors and confidence interval bounds of each regression are stored as a data frame of the form:
## regression1:
var betas crse upper lower
1 x1 0.517251974 0.58176862 0.37751553 0.05698842
2 x2 -0.260210445 0.03521915 -0.12118217 -0.25923872
3 x3 0.680752318 0.08844444 0.75410023 0.40740441
4 x4 0.663395004 0.05090350 0.26316403 0.06362598
5 x5 -0.551992451 0.03289870 -0.08751219 -0.21647271
## regression2:
var betas crse upper lower
1 x1 -0.343254719 0.05498965 0.01451302 -0.20104246
2 x2 0.126434568 0.02243139 0.17040108 0.08247165
3 x3 -0.178460203 0.06215729 -0.05663415 -0.30028625
4 x4 0.301058265 0.03737595 0.37431378 0.22780275
5 x5 -0.054594805 0.02037967 -0.01465139 -0.09453822
My approach was to combine both regressions into one data frame using:
combined <- rbind(regression1, regression2)
And then I use ggplot
:
ggplot(combined, aes(x=var, y=betas)) +
geom_point(aes(x=var, y=betas),
color="red",
shape=15) +
geom_errorbar(aes(ymin=lower, ymax=upper),
width=.25,
size=.65)
However, the lines of the two models with the coefficient / confidence intervals overlap each other in the plot and it is not easy to distinguish which one is which. Is there a way to separate the lines so that they can be distinguished? Perhaps I am using the wrong approach and I should not rbind
the two plots.
Upvotes: 1
Views: 490
Reputation: 73134
You may use matplot
. However, your regression seems to be flawed, since betas don't lie between the CI's.
matplot(regression1[, c(2, 4:5)], type='l', lty=c(1, 2, 2), col=1)
matlines(regression2[, c(2, 4:5)], type='l', lty=c(1, 2, 2), col=2)
legend('topright', legend=paste('r', 1:2), text.col=1:2, bty='n')
Upvotes: 2
Reputation: 226522
@user2602640's answer gets the essential points but there are a couple of additional shortcuts you can use.
dplyr::bind_rows()
will automatically set up an "id" column (you need to name the arguments, which is a little annoying; otherwise the id reverts to numeric indices)geom_pointrange()
will do both the points and the CIs at the same time (perhaps there's an analogous combined-points-and-errorbars geom out there somewhere in the extended ggplot-verse?)broom
and dotwhisker
packages, which can further streamline similar tasks (e.g. if you have two regressions dotwhisker::dwplot(r1, r2)
will automatically construct the combined coefficient plot)The chosen width (0.25) for position_dodge()
is an aesthetic choice you may want to adjust (ggplot dodges geoms like boxplots automatically, but considers points zero-width, so you need to specify an amount of displacement)
library(tidyverse)
combined <- bind_rows(reg1=reg1, reg2=reg2, .id="model")
ggplot(combined, aes(x=var, y=betas, ymin=lower, ymax=upper, colour=model)) +
geom_pointrange(position=position_dodge(width=0.25))
reg1 <- read.table(header=TRUE, text="
var betas crse upper lower
x1 0.517251974 0.58176862 0.37751553 0.05698842
x2 -0.260210445 0.03521915 -0.12118217 -0.25923872
x3 0.680752318 0.08844444 0.75410023 0.40740441
x4 0.663395004 0.05090350 0.26316403 0.06362598
x5 -0.551992451 0.03289870 -0.08751219 -0.21647271
")
reg2 <- read.table(header=TRUE, text="
var betas crse upper lower
x1 -0.343254719 0.05498965 0.01451302 -0.20104246
x2 0.126434568 0.02243139 0.17040108 0.08247165
x3 -0.178460203 0.06215729 -0.05663415 -0.30028625
x4 0.301058265 0.03737595 0.37431378 0.22780275
x5 -0.054594805 0.02037967 -0.01465139 -0.09453822
")
Upvotes: 1
Reputation: 816
You just need to create a new variable to track the two regressions and allow the colour of the points / errorbars change with that variable. The dodging allows to separate the two regressions sideways. So:
regression1$Reg <- "Regression 1"
regression2$Reg <- "Regression 2"
combined <- rbind(regression1, regression2)
ggplot(combined, aes(x=var, y=betas)) +
geom_point(aes(x=var, y=betas, colour = Reg),
shape=15, position = position_dodge(width = 0.25)) +
geom_errorbar(aes(ymin=lower, ymax=upper, colour = Reg),
width=.25, position = position_dodge(width = 0.25),
size=.65)
Upvotes: 2