2
votes

I'm trying to connect ggplot2 boxplots with geom_lines for multiple factors. I'd been able to accomplish so far to connect all the boxplot with lines, see attach picture. But I wish to connect the only boxplots by their corresponding factor.

enter image description here

For example for my variable FL, I want to connect only those two boxplot, without connecting them with the remaining variables. Similarly for the variable RW, connecting those two sex boxplot without the remaining others.

library("MASS")  
data(crabs)  
melt_crabs <- melt(crabs,id.var=c("sp","sex","index"))   
ggplot(melt_crabs, aes(x = variable, y = value)) +   geom_line(aes(group = index), size = 0.05, alpha = 0.7) +   geom_boxplot(aes(fill = sp), alpha = 0.5) + facet_grid(sex~.)

Does anyone know how to achieve this? I hope I'd explain myself the most clear way.

Many thanks and best wishes,

2
Your code does not produce the figure you show. I think you just exchanged sex and sp.Stibu
@Stibu Thanks for replying and editing the code. I'm new at this and I thought it was displayed my apologies. The used of sex and sp is not impotant. The example here is to have two boxplot in the same factor and connect them. Many thanks.Stat_Isra

2 Answers

5
votes

I don't know of way to connect the points in exactly the plot that you produced. But I can show you how to do something similar.

The difficulty is that all the points that belong to a pair of boxplots share the same x-coordinate (that is, the same value for variable). Therefore I have used interaction(sex, variable) as the x-coordinate, such that each boxplot has its own x-value. This means, however, that the paired boxplots are less visible. On the other hand, the connecting lines work in the other direction.

In order to plot the lines, they are grouped by interaction(index, variable), which means that data points are connected, when they share the same values for index and variable.

Enough talk, here's the code:

ggplot(melt_crabs, aes(x = interaction(sex, variable), y = value)) +
    geom_boxplot(aes(fill = sex), alpha = 0.5) +
    geom_line(aes(group = interaction(index, variable)),
              alpha = 0.5, colour = "darkgrey") +
    facet_grid(sp~.) +
    scale_x_discrete(labels = rep(levels(melt_crabs$variable), each = 2))

enter image description here

4
votes

@Stibu's answer is definitely the quickest and cleanest way to get your desired output. Building off his answer, since for a given variable, the plots are no longer next to each other, you might want to put each in their own separate plot. This can be easily by only a minor tweak to the facet_grid call in @Stibu's code:

ggplot(melt_crabs, aes(x = interaction(sex, variable), y = value)) +
  geom_boxplot(aes(fill = sex), alpha = 0.5) +
  geom_line(aes(group = interaction(index, variable)),
            alpha = 0.5, colour = "darkgrey") +
  facet_grid(sp~variable,scales="free_x") +
  scale_x_discrete(labels = "")

enter image description here

Also I did some digging if you want to move the top strip to the bottom, it isn't that difficult. Adapting the code from: How to display strip labels below the plot when faceting?

We get:

p<-ggplot(melt_crabs, aes(x = interaction(sex, variable), y = value)) +
  geom_boxplot(aes(fill = sex), alpha = 0.5) +
  geom_line(aes(group = interaction(index, variable)),
            alpha = 0.5, colour = "darkgrey") +
  facet_grid(sp~variable,scales="free_x") +
  scale_x_discrete(labels = "")

# Convert the plot to a grob
gt <- ggplotGrob(p)

# Get the positions of the panels in the layout: t = top, l = left, ...
panels <-c(subset(gt$layout, name == "panel", select = t:r))

# Get the strip grob & x-axis label grob
stripGrob = gtable_filter(gt, "strip-top")

#Replace x-axis ticks with strip
gt = gtable_add_grob(gt, stripGrob, t = max(panels$b)+1, l = min(panels$l), r = max(panels$r))

# remove the old strip
gt = gt[-(min(panels$t)-1), ]

grid.newpage()
grid.draw(gt)

enter image description here