1

I'm trying to plot data from several columns of a dataframe. Each column represents the y value and for each of those, the x-value range from 0 to 100. When trying to graph this data, they y-axis looks like a giant mess(there are 12 columns). If I can set a minimum y value of 0 and a max of 1700 or so, things should workout. How do I do this? Also how do I extend the x axis so that I may add a legend next to it(How do I do that here?) ggplot is not being recognized by my Rstudio so I used this code

plot(x-axis, y1)
par(new=T)
plot(x-axis, y2, col="darkcyan")
par(new=T)
plot(x-axis, y3, col="green")
par(new=T)
plot(x-axis, y4, col="orange")
par(new=T)
...
plot(x-axis, y12, col="blue")
par(new=T)

Here's what this looks like: enter image description here

I also wrote this other code to do the same thing.

matplot(x-axis, 
cbind(aaaa,aaab,aaac,aaad,aaae,aaaf,aaag,aaah, 
aaai,aaaj, aaak,aaal),type="l",col=c("red", "blue", 
"green", "cyan", "darkcyan", "azure", 
"darkkhaki","aquamarine", "brown1","deeppink", 
"deepskyblue1", "blueviolet"), xlab="Return Period 
(Years)", ylab="Return Years (mm)" )
legend("topright", colnames(dfreturnplot2), col=12, 
cex=0.8, fill=seq_len(12))

Here, the y-axis looks fine but legend is interfering with the visibility of the graph. I can't just make a longer x-dimension by lengthening x-axis so what I should do?

Here's what this looks like enter image description here

After following Jay's advice, I now get enter image description here

Is there a way to make the screen bigger so someone looking at this can see what's going? Is there an alpha value like in python so that we can see through a curve that's on top of several others?

After using Jay's second suggestion, I get (I still have to read the link he provided) enter image description here

I also looked at using ggplot2. Using this code: enter image description here

I get this image: enter image description here

How do I add a legend to this. I feel like it should be very easy but I'm missing something and Evans answer is a bit confusing for me right now. Is there a way to add a label right after the color?

I have this image enter image description here

I don't see a parameter within geompoint that I can use to add a label to the curves individually. Am I missing something?

Jama
  • 113
  • 5
  • 1
    I'm familiar with `matplot`, I could help you if you could provide an example that I could reproduce. Have you read our [tutorial](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) on how to do this very quickly? – jay.sf Jul 12 '22 at 07:45
  • this is still not reproducible: `Error in is.data.frame(x) : object 'dfreturnplot2' not found` – gaut Jul 12 '22 at 07:50
  • @gaut dfreturnplot is a dataframe which holds the column names. the legend comes from those names. Jay, unfortunately I don't think I can. It's from several excel files – Jama Jul 12 '22 at 08:10
  • `ggplot is not being recognized by my Rstudio` have you tried installing the package? `install.packages('ggplot2')` – gaut Jul 12 '22 at 08:17
  • there was an issue with it but I fixed it. thanks – Jama Jul 12 '22 at 18:10

2 Answers2

3

Extend the ylim by a factor say *1.1 and make a frameless horizontal legend.

matplot(m, type='l', lty=1, ylim=c(min(m), max(m)*1.1))
legend("topleft", colnames(m), col=12, cex=0.8, fill=seq_len(12), horiz=TRUE, bty='n')

enter image description here

If you have even more items, there's also a ncol= argument in legend to present them in a multicolumn matrix, see ?legend.

matplot(m, type='l', lty=1, ylim=c(min(m), max(m)*1.1))
legend("topleft", LETTERS[1:20], col=12, cex=0.8, fill=seq_len(20), ncol=10, bty='n')

enter image description here

You may also extend the xlim and leave the frame on, this is really very flexible.

matplot(m, type='l', lty=1, xlim=c(0, nrow(m)*1.25))
legend("right", LETTERS[1:26], col=12, cex=0.8, fill=seq_len(20), ncol=2)

enter image description here


Data:

m <- sapply(1:10, \(x) plogis(seq(0, 10, .1)/x)) |> `colnames<-`(LETTERS[1:10])
jay.sf
  • 60,139
  • 8
  • 53
  • 110
  • yours looks really nice. I realized that I shouldnt be using lines but instead little dots (since for each value from 1 to 100, there is one return value). Is there a way to do this so that there is some visibility. And how do I make the plot bigger so that it is more clear. I found posts referiring to using windows() function but nothing happens – Jama Jul 12 '22 at 18:10
  • 1
    @Jama Try `type='p', pch=16` in `matplot`, the latter refers to point characters, see `?pch` for all the options. For the size, get used to use another _device_ as explained here: https://stackoverflow.com/a/7144203/6574038 The advantage is that you may define a fixed size, and nothing gets broken which is more fun :) – jay.sf Jul 12 '22 at 18:17
  • @Jama Just reviewed the edits to your question. You appear to have problems with the margins. I'm not quite sure why though (you just provide results but no reproducible code). _Solutions:_ Sometimes legends get distorted by rescaling the Rstudio preview window; use a different [device](https://stackoverflow.com/a/7144203/6574038). You may also try to [adjust the margins](https://stackoverflow.com/questions/65816279/adjusting-margins-for-r-plots), e.g. `par(mar=c(5, 4, 4, 5))`, see `?par`. – jay.sf Aug 26 '22 at 06:35
2

I urge trying to use ggplot2 here: it does legends very well and automatically shifts things around to make everything fit.

ggplot is not being recognized by my Rstudio so I used this code

Try install.packages("ggplot2"); if it fails, some quick research should inform how to get it installed.

Using @jay.sf's sample data, we just need to melt it and ggplot2 does the rest:

library(ggplot2)
transform(m, x = seq_len(nrow(m))) |>
  reshape2::melt("x", variable.name = "grp", value.name = "y") |>
  ggplot(aes(x, y, color = grp)) +
  geom_line() +
  guides(color = guide_legend(ncol = 2))

basic ggplot2

ggplot2 allows you to customize a lot, including multi-column legends (as shown, defaults to 1), removing legend titles, cleaning up the background/theme (add + theme_bw()), varying color/size/linetype/... by group/line/..., etc. Learn its semantics once and you will forever benefit from its ability to control great-looking plots (versus base graphics where you have to wrestle control for large legends manually).

r2evans
  • 141,215
  • 6
  • 77
  • 149
  • could you explain what your code is doing? I installed ggplot2 and called library(ggplot2). My method involved using a bunch of geom_scatter but turns out that doesn't exist and I was actually looking for geom_point. Took me a while to figure that out – Jama Jul 12 '22 at 18:05
  • The use of `melt` is reshaping from "wide" (different categories in each column, all used as `y` values) to "long" (a single column of `y` values, a single column that contains the column from which each "y" value is taken). For reshaping from wide-to-long, see https://stackoverflow.com/q/2185252/3358272, and you can use `tidyr::pivot_longer`, `reshape2::melt`, or `data.table::melt`; for long-to-wide see https://stackoverflow.com/q/11608167/3358272, use `tidyr::pivot_wider`, `reshape2::dcast`, and `data.table::dcast`. – r2evans Jul 12 '22 at 18:17
  • what is "grp" and "y"? I followed those links but couldn't understand most of it yet – Jama Jul 17 '22 at 08:37
  • `y` contains all of the actual values. `grp` contains the names of the columns from which they came. It's easier to see the changed data on than to explain it in a comment, just run the first two lines of code (`transform` and `melt`). – r2evans Jul 17 '22 at 09:40
  • it's hard to match which color goes with which graph. Is there a way to make that distinction more obvious? Like is there a way to make it so that the colors in the legend appear in the same order as the curves in the graph? – Jama Aug 26 '22 at 06:11
  • Yes, any question that asks *"how to order (axis|legend) in ggplot2"* is resolved by using factors (explicitly controlling the order of the `levels=`). Determine the order you want (whether reversing, as here, or perhaps based on the order of the data) into `neworder <- LETTERS[10:1]`, and insert `transform(grp = factor(grp, levels = neworder))` in the `|>`-pipe between `melt(.)` and `ggplot(.)`. – r2evans Aug 26 '22 at 10:47