Asked  7 Months ago    Answers:  5   Viewed   31 times

I would like superimpose two scatter plots in R so that each set of points has its own (different) y-axis (i.e., in positions 2 and 4 on the figure) but the points appear superimposed on the same figure.

Is it possible to do this with plot?

Edit Example code showing the problem

# example code for SO question
y1 <- rnorm(10, 100, 20)
y2 <- rnorm(10, 1, 1)
x <- 1:10
# in this plot y2 is plotted on what is clearly an inappropriate scale
plot(y1 ~ x, ylim = c(-1, 150))
points(y2 ~ x, pch = 2)



update: Copied material that was on the R wiki at, link now broken: also available from the wayback machine

Two different y axes on the same plot

(some material originally by Daniel Rajdl 2006/03/31 15:26)

Please note that there are very few situations where it is appropriate to use two different scales on the same plot. It is very easy to mislead the viewer of the graphic. Check the following two examples and comments on this issue (example1, example2 from Junk Charts), as well as this article by Stephen Few (which concludes “I certainly cannot conclude, once and for all, that graphs with dual-scaled axes are never useful; only that I cannot think of a situation that warrants them in light of other, better solutions.”) Also see point #4 in this cartoon ...

If you are determined, the basic recipe is to create your first plot, set par(new=TRUE) to prevent R from clearing the graphics device, creating the second plot with axes=FALSE (and setting xlab and ylab to be blank – ann=FALSE should also work) and then using axis(side=4) to add a new axis on the right-hand side, and mtext(...,side=4) to add an axis label on the right-hand side. Here is an example using a little bit of made-up data:

x <- 1:10
y <- rnorm(10)
## second data set on a very different scale
z <- runif(10, min=1000, max=10000) 
par(mar = c(5, 4, 4, 4) + 0.3)  # Leave space for z axis
plot(x, y) # first plot
par(new = TRUE)
plot(x, z, type = "l", axes = FALSE, bty = "n", xlab = "", ylab = "")
axis(side=4, at = pretty(range(z)))
mtext("z", side=4, line=3)

twoord.plot() in the plotrix package automates this process, as does doubleYScale() in the latticeExtra package.

Another example (adapted from an R mailing list post by Robert W. Baer):

## set up some fake test data
time <- seq(0,72,12)
betagal.abs <- c(0.05,0.18,0.25,0.31,0.32,0.34,0.35)
cell.density <- c(0,1000,2000,3000,4000,5000,6000)

## add extra space to right margin of plot within frame
par(mar=c(5, 4, 4, 6) + 0.1)

## Plot first set of data and draw its axis
plot(time, betagal.abs, pch=16, axes=FALSE, ylim=c(0,1), xlab="", ylab="", 
   type="b",col="black", main="Mike's test data")
axis(2, ylim=c(0,1),col="black",las=1)  ## las=1 makes horizontal labels
mtext("Beta Gal Absorbance",side=2,line=2.5)

## Allow a second plot on the same graph

## Plot the second plot and put axis scale on right
plot(time, cell.density, pch=15,  xlab="", ylab="", ylim=c(0,7000), 
    axes=FALSE, type="b", col="red")
## a little farther out (line=4) to make room for labels
mtext("Cell Density",side=4,col="red",line=4) 
axis(4, ylim=c(0,7000), col="red",col.axis="red",las=1)

## Draw the time axis
mtext("Time (Hours)",side=1,col="black",line=2.5)  

## Add Legend
legend("topleft",legend=c("Beta Gal","Cell Density"),

enter image description here

Similar recipes can be used to superimpose plots of different types – bar plots, histograms, etc..

Tuesday, June 1, 2021
answered 7 Months ago
boxplot(a, at = 0:2*3 + 1, xlim = c(0, 9), ylim = range(a, b), xaxt = "n")
boxplot(b, at = 0:2*3 + 2, xaxt = "n", add = TRUE)
axis(1, at = 0:2*3 + 1.5, labels = colnames(a), tick = TRUE)

Note the ylim = range(a, b) parameter. The plot scale is determined by the first command, but if b contained values out of range of values in a (not in this case, but try to swap a and b), they would lie out of the plot. That's why in general you should specify the ylim here.

You can also set tick = FALSE in the axis() command, I think it is nicer. If you don't like the space between the groups, use 0:2*2 instead of 0:2*3, and change the xlim appropriatelly.

Thursday, September 16, 2021
answered 3 Months ago

Look at the parameters xaxs and yaxs (under ?par). By default the axis contains the data range plus 4% on either side. If you override the parameter, then you can get an axis exactly equal to the data range. Cf:

> curve(x^2)

> curve(x^2, xaxs="i", yaxs="i")
Tuesday, September 28, 2021
answered 2 Months ago

You must add scale_color_identity in order for colors to be taken "as is" :

ggplot(data=image.rgb, aes(x=x, y=y, col=rgb(r,g,b))) + 
    geom_point() + 

The sample data you provided give very similar colors, so all the points seem to be black. With geom_tile the different colors are a bit more visible :

ggplot(data=image.rgb, aes(x=x, y=y, fill=rgb(r,g,b))) +
    geom_tile() +

enter image description here

Sunday, October 17, 2021
answered 2 Months ago

I think I have a working solution for you. In plotly js and plotly R the colors are the same. So I write a little javascript code that creates 6 traces in a barchart with plotly.js and print afterwards the colors of each bar to the console and in an alert. I created a jsFiddle for that:

So the first colors are:

#1f77b4 or rgb(31, 119, 180)  // muted blue
#ff7f0e or rgb(255, 127, 14)  // safety orange
#2ca02c or rgb(44, 160, 44)   // cooked asparagus green
#d62728 or rgb(214, 39, 40)   // brick red
#9467bd or rgb(148, 103, 189) // muted purple
#8c564b or rgb(140, 86, 75)   // chestnut brown
#e377c2 or rgb(227, 119, 194)
#7f7f7f or rgb(127, 127, 127)
#bcbd22 or rgb(188, 189, 34)
#17becf or rgb(23, 190, 207)

Hope it helps:-)

Edit from 2020 by comment of Despe1990: Since plotly 4 (in python and R maybe? I cannot see changes of color palette in plotly js) the first 3 default colors have changed: #636efa, #ef553b and #00cc96

Sunday, October 31, 2021
Preet Sangha
answered 1 Month ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :