user507
user507

Reputation: 233

Plot multiple columns against a single column in one plot in R

I have a dataframe with 9 columns, including a column for elapsed time (Days):

Probes <- data.frame(Days=seq(0.01, 4.91, 0.01), DJ1=-45:445, SJ2=-50:440, SJ3=10:500, SJ4=-200:290, DJ2=-150:340, DJ9=100:590, SJ21=-300:190, SJ32=-100:390) 

I would like to create a line graph with multiple series on one plot. I would be plotting EACH of the remaining columns in the data frame against the first column (Days).

I know the basic code to do this...However, I am wondering if there is a simpler option for when you would like to plot ALL of the columns in the dataframe against one column, as I am doing now. It seems redundant to have to type a line of code for every single column name, particularly because I have to this on over 50 data frames.

For my particular dataset, I would like to color the columns with "S" in the header as "brown" and the columns with "D" in the header as orange.

The long and unwieldy code I have for this is written below so that you can see the output I am going for. Is there a simpler way to this (perhaps in ggplot)?

png("ProbesPlot.png", height = 1000, width = 1400, units = "px", res = 200)
par(xpd=T, mar=par()$mar+c(0,0,0,6))
plot(Probes$Days, Probes$DJ1, type="l", lwd=2, lty=1, col="orange", main="Depth in Sediments- 4.5 cm", xlab="Elapsed Time (days)", ylab="Eh (mV)", xlim=c(0, 8), ylim=c(-400,600), bty="n") 
lines(Probes$Days, Probes$SJ2, type="l", lwd=2, lty=1, col="brown")
lines(Probes$Days, Probes$SJ3, type="l", lwd=2, lty=1, col="brown")
lines(Probes$Days, Probes$SJ4, type="l", lwd=2, lty=1, col="brown")
lines(Probes$Days, Probes$DJ2, type="l", lwd=2, lty=1, col="orange ")
lines(Probes$Days, Probes$DJ9, type="l", lwd=2, lty=1, col="orange ")
lines(Probes$Days, Probes$SJ21, type="l", lwd=2, lty=1, col="brown")
lines(Probes$Days, Probes$SJ32, type="l", lwd=2, lty=1, col="brown")
legend(8.5,400, c("4 cm", "1 cm"), lty=c(1,1),  lwd=c(2,2), col=c("orange", " brown"), bty="n", title="Depth") 
dev.off() 

3/1 Edit to question @eipi10 I have an additional dataframe with 29 columns including a column for elapsed time (Days). I would like to create the same type of plot, but instead of 2 color categories (D and S) I now have 3 (D, M, and S). This is an example of the structure of my new dataframe:

Probes <- data.frame(Days=seq(0.01, 4.91, 0.01), B1D.J1=-45:445, B1S.J2=-50:440, B1M.J3=10:500, B1S.J4=-200:290, B1D.J25=-150:340, B1D.J9=100:590, B1S.J21=-300:190, B1S.J32=-100:390, B1D.J18=-15:475, B1M.J22=-70:420, B1M.J31=5:495, B1S.J43=-200:290, B1D.J27=-150:340, B1D.J99=100:590, B1S.J87=-300:190, B1S.J65=-100:390, B1S.J44=-300:190, B1M.J90=-100:390, B1D.J18=-15:475, B1M.J26=-70:420, B1M.J66=5:495, B1M.J43=-200:290, B1D.J52=-150:340, B1D.J96=-50:440, B1M.J53=-300:190, B1M.J74=-100:390)

Also, the only legend I would essentially need is a small one differentiating the colors: Orange=Deep, Brown= Mid, Red=Shallow (D, M, and S)

Upvotes: 0

Views: 4563

Answers (2)

eipi10
eipi10

Reputation: 93871

Following @MikeWise's suggestion, here's how you can make this much easier with ggplot2:

library(ggplot2)
library(reshape2)
library(dplyr)

Probes <- data.frame(Days=seq(0.01, 4.91, 0.01), DJ1=-45:445, SJ2=-50:440, SJ3=10:500, SJ4=-200:290, DJ2=-150:340, DJ9=100:590, SJ21=-300:190, SJ32=-100:390) 

# Convert data to long format
Probes.m = melt(Probes, id.var="Days")

# Reorder factor levels so "D's" and "S's" are grouped together
Probes.m$variable = factor(Probes.m$variable, 
                           levels=sort(unique(as.character(Probes.m$variable))))

ggplot(Probes.m, aes(Days, value, colour=variable)) +
  geom_line() +
  scale_colour_manual(values=rep(c("orange","brown"), c(3,5))) +
  guides(colour=FALSE) +
  geom_text(data=Probes.m %>% group_by(variable) %>% filter(value==max(value)),
            aes(label=variable, x=Days + 0.1, y=value), size=3, hjust=0) +
  labs(x="x-label", y="y-label") +
  ggtitle("My Title")

enter image description here

UPDATE: Based on your comment and the updated data you provided, the issue is that many of your lines exactly overlap, so they plot one on top of the other. You can see this by inspecting your sample data. Also, using your new data and using geom_text_repel instead of geom_text you can see there are multiple labels for the "same" line, which is really just multiple copies of the same line with different names.

ggplot(Probes.m, aes(Days, value, colour=variable)) +
  geom_line() +
  scale_colour_manual(values=rep(c("orange","brown","red"), c(9,9,8))) +
  guides(colour=FALSE) +
  geom_text_repel(data=Probes.m %>% group_by(variable) %>% filter(value==max(value)),
            aes(label=variable, x=Days + 0.1, y=value), size=3) +
  labs(x="x-label", y="y-label") +
  ggtitle("My Title")

enter image description here

Upvotes: 3

Nick F
Nick F

Reputation: 311

Building on answer from @eipi10, to cope with overlapping text you could make use of a new package ggrepel which provides a new 'geom' for ggplot. [I started answering this earlier using tidyr instead of reshape2 and don't have reputation to comment yet so posting this as new answer]

library(ggplot2)
library(tidyr)
library(dplyr)
library(ggrepel)

Probes <- data.frame(Days=seq(0.01, 4.91, 0.01), DJ1=-45:445, SJ2=-50:440, SJ3=10:500, SJ4=-200:290, DJ2=-150:340, DJ9=100:590, SJ21=-300:190, SJ32=-100:390)

tidiedProbes <-
  Probes %>%
  tidyr::gather(key = probeRef, value = `Eh (mV)`, - Days) %>%
  dplyr::mutate(lineColour = ifelse(substring(probeRef, 1, 1) == "D", "D", "S"))

dataForLabels <-
  tidiedProbes %>%
  filter(Days == max(Days))

newPlot <- 
  tidiedProbes %>%
  ggplot() +
  geom_line(aes(x = Days, y = `Eh (mV)`, colour = lineColour, group = probeRef)) + 
  scale_color_manual(values = c("orange", "brown")) +
  geom_text_repel(
      data = dataForLabels, 
      aes(x = Days, y = `Eh (mV)`, label = probeRef)) +
  ggtitle("Depth in Sediments - 4.5 cm") + 
  xlab("Elapsed Time (days)") +
  theme(legend.title = element_blank())
newPlot

Don't have reputation for posting images yet but hopefully plot looks as expected

Upvotes: 1

Related Questions