Plotting x-axis values at intervals - r

I will like to plot some data, with the x-axis data plotted at intervals
X:
50.0000
100.5467
689.7431
1559.8025
1000.9365
10.9095
Y:
-0.0596123270783229
0.644158691971081
-0.433854284204926
-0.365746109442603
0.566685929975495
0.398462720589891
Function:
plotM<- function( dat, m ) {
plot(data$X, data$Y,
log="x", pch=20, cex=0.7,
col = ifelse( data$Y < m, "red", "black" ),
xlab = "Y", ylab = expression(Log[2]~Fold~Change))
}
Function call:
plotM(dat, .05)
How can I plot the data with the following sequence in x-axis:
10, 100, 1000, 2000
Thanks

You need to create a plot with no axes then add them manually.
Using some example data
x = 10^(0:3)
y = 0:3
We plot x and y and specify no axis are to be plotted:
plot(x, y, log="x", axes=FALSE, frame=TRUE)
Then add on the x and y axis manually
## See ?axis for more details
axis(1, 10^(0:3), 10^(0:3))
axis(2)
Alternatively, we can be a bit more fancy with the axis labels to get
axis(1, 10^(0:3), c(expression(10^0),
expression(10^1),
expression(10^2),
expression(10^3)))
to get

Try this... I have used ggplot2, much used graphical package of R.
It will create x axis on log scale using ggplot..
ggplot(data = data) + geom_line(aes(x = x, y = y)) + scale_x_log10()
This is how results will look like...

Related

GGplot second y axis without the transformation of y axis

Does any one know how do you apply this
set.seed(101)
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)
but using ggplot.
In ggplot you can only create sec.axis() or dup.axis() using a transformation of y axis. What about a whole new independent y axis which will be applied only for z variable and the simple y axis to be applied for the y variable.
ggplot2::sec_axis provides only one mechanism for providing a second axis, and it took a lot of convincing to get that into the codebase. You are responsible for coming up with the transformation. This transform must be linear in some way, so if either axis needs to be non-linear (e.g., exponential, logarithmic, etc), then your expert math skills will be put to the test.
If you can use scales, then this process becomes trivial:
dat <- data.frame(x, y, z)
ggplot(dat, aes(x, y)) +
geom_point() +
geom_line(
aes(y = zmod),
data = ~ transform(., zmod = scales::rescale(z, range(y), range(z)))
) +
scale_y_continuous(
sec.axis = sec_axis(~ scales::rescale(., range(dat$z), range(dat$y)),
breaks = c(2000,4000,6000,8000))
)
Unless I've missed something (I just checked ggplot2-3.3.5's NEWS.md file), this has not changed.

How to overlay 3 functions on one plot using R

I have three functions and a plot code:
f1 <- function(c){0.187*c-0.000236*c^2+0.194*10-0.00330*100-0.000406*10}
f2 <- function(c){0.187*c-0.000236*c^2+0.194*16.53-0.00330*(16.53^2)-0.000406*16.53}
f3 <- function(c){0.187*c-0.000236*c^2+0.194*20-0.00330*400-0.000406*20}
I wish to plot all three of these on the same graph. I currently have:
png("figure.png")
plot(f1(1:1000), type="l", xlab="x", ylab="y", main="the plot :)")
plot(f2(1:1000), type="l", xlab="x", ylab="y", add = T)
dev.off()
So far this produces just f1 on a plot as opposed to f1 and f2. I believe I am taking the wrong approach because I am producing another plot and trying to add it to a pre-existing plot. I am unsure whether to use geom_line or something similar and just overlay it.
Is there a straight forward way to plot multiple functions and overlay them in the same plot?
geom_line is for ggplot2, which is an entirely different plotting system.
If you start with plot(), you can use lines() to draw lines on your current plot. Your lines are pretty close together, so it doesn't matter much here, but with base plot you usually want to calculate the maximum range in advance so your can set your plot window up right from the start:
x = 1:1000
y1 = f1(x)
y2 = f2(x)
y3 = f3(x)
y_range = range(c(y1, y2, y3))
plot(x, y1, ylim = y_range, type="l", xlab="x", ylab="y", main="the plot :)", col = "red")
lines(x, y2, col = "blue")
lines(x, y3, col = "chartreuse")
ggplot2 is made to work with data in data frames - particularly long-format data frames. Here's how we might approach the problem with ggplot. (Note that, unlike above, ggplot calculates the plot limits and gives a nice legend automatically.)
library(ggplot2)
dd = data.frame(x, y1, y2, y3)
d_long = reshape2::melt(data = dd, id.vars = "x", variable.name = "fun", value.name = "y")
ggplot(d_long, aes(x = x, y = y, color = fun)) +
geom_line()
OR sticking with base R plotting like your code, you can just add the extra functions using lines
plot(f1(1:1000), type="l", xlab="x", ylab="y", main="the plot :)")
lines(1:1000, f2(1:1000))
lines(1:1000, f3(1:1000))
If you want two plots one right next to the other, you have to set the parameter of your palette. Use par(mfrow=c(1,2)) after the png() command.
png("figure.png")
par(mfrow=c(1,2))
plot(f1(1:1000), type="l", xlab="x", ylab="y", main="the plot :)")
plot(f2(1:1000), type="l", xlab="x", ylab="y", add = T)
dev.off()
For functions you can also use curve:
f1 <- function(c){0.187*c-0.000236*c^2+0.194*10-0.00330*100-0.000406*10}
f2 <- function(c){0.187*c-0.000236*c^2+0.194*16.53-0.00330*(16.53^2)-0.000406*16.53}
f3 <- function(c){0.187*c-0.000236*c^2+0.194*20-0.00330*400-0.000406*20}
c0 <- 1
c <- 1000
curve(f1, c0, c, main = 'the plot :)', xlab = 'x', ylab = 'y')
curve(f2, c0, c, add = T)
curve(f3, c0, c, add = T)
As #Gregor noted, geom_line() is a ggplot() call. To go all into the tidyverse, you can do:
#or with ggplot / geom_line
library(tidyverse)
map_df(list(f1 =f1,f2 = f2,f3 = f3), exec, 1:1000)%>%
mutate(x = 1:1000)%>%
gather(key = fx,value = value, -x)%>%
ggplot(aes(x = x, y = value, col = fx)) + geom_line()
Finally, you may be interested in facet_grid as well:
map_df(list(f1 =f1,f2 = f2,f3 = f3), exec, 1:1000)%>%
mutate(x = 1:1000)%>%
gather(key = fx,value = value, -x)%>%
ggplot(aes(x = x, y = value)) + geom_line() +
facet_grid(rows = vars(fx))

Reverse the scale of the x axis in a plot

I have created a plot in R and my own custom x and y axes. I would like the x axis to be displayed in a reverse order (1-0 by -.02). I have read numerous posts and threads that suggest using xlim and reverse range but I just can't seem to make it work. Once plotted I am also converting the axes labels to percentages by multiplying by 100 (as you will see in the code). Here is what I have so far;
plot(roc.val, xlab = "Specificity (%)", ylab = "Sensitivity (%)", axes = FALSE)
axis(2, at = seq(0,1,by=.2), labels = paste(100*seq(0,1, by=.2)), tick = TRUE)
axis(1, at = seq(0,1,by=.2), labels = paste(100*seq(0,1, by=.2)), tick = TRUE)
How can I reverse the x axis scale so that the values begin at 100 and end at 0 with increments of 20?
I think this creates a plot in which the y-axis is in reverse order:
x <- seq(-4, 4, length = 10)
y <- exp(x) / (1 + exp(x))
plot(x,y, ylim = rev(range(y)))
This removes the axis values:
x <- seq(-4, 4, length = 10)
y <- exp(x) / (1 + exp(x))
plot(x,y, ylim = rev(range(y)), labels = FALSE)
I guess you can assign the axis values you want then with a variation of your lines:
axis(2, at = seq(0,1,by=.2), labels = paste(100*seq(0,1, by=.2)), tick = TRUE)
axis(1, at = seq(0,1,by=.2), labels = paste(100*seq(0,1, by=.2)), tick = TRUE)
df <- data.frame(x=seq(0,1, length.out=50), y=seq(0, 1, length.out=50))
plot(df)
df$x1 <- (max(df$x) - df$x)/ (max(df$x) - min(df$x))
plot(df$x1, df$y, axes=F, xlab = "Specificity (%)", ylab = "Sensitivity (%)")
axis(2, at = seq(0,1,by=.2), labels = paste(100*seq(0,1, by=.2)), tick = TRUE)
axis(1, at = seq(0,1,by=.2), labels = paste(100*seq(1,0, by=-.2)), tick = TRUE)
Adapting Mark Miller's answer to solve a similar problem (I found this topic by looking for the solution) and I found a variation of his solution in https://tolstoy.newcastle.edu.au/R/help/05/03/0342.html.
Basically if you want to reverse the X-axis values in the plot, instead of using ylim=rev(range(y)), you can use xlim=rev(c(-4,4)).
x <- seq(-4, 4, length = 10)
y <- exp(x) / (1 + exp(x))
par(mfrow=c(1,2))
plot(x, y, ylim=range(y), xlim=c(-4, 4))
plot(x, y, ylim=range(y), xlim=rev(c(-4, 4)))
plot1
And if you want to keep the x-axis values in the true order, you can use this:
par(mfrow=c(1,1))
plot(x, y, ylim=range(y), xlim=c(-4, 4), axes=FALSE)
par(new=TRUE)
plot(-100, -100, ylim=range(y), xlim=c(-4, 4), axes=FALSE, xlab="", ylab="", main="")
axis(1, at = seq(-4,4,by=1), labels = seq(-4,4,by=1), tick = TRUE)
axis(2, at = seq(0,1,by=.2), labels = paste(100*seq(0,1, by=.2)), tick = TRUE)
plot2
I'm posting this solution because I needed something very straightforward to solve my problem. And the solution for it needed the plot with the X-axis value in the correct order (and not reversed).
First, check out the ggplot2 library for making beautiful and extendable graphics. It is part of the Tidyverse approach to R and a gamechanger if you have not been exposed to it.
For example, to solve your issue using ggplot, you simply add the term scale_x_reverse() to your graphic.
See: http://ggplot.yhathq.com/docs/scale_x_reverse.html

Plotting two Poisson processes on one plot

I have two Poisson processes:
n <- 100
x <- seq(0, 10, length = 1000)
y1 <- cumsum(rpois(1000, 1 / n))
y2 <- -cumsum(rpois(1000, 1 / n))
I would like to plot them in one plot and expect that y1 lies above x-axis and y2 lies below x-axis. I tried the following code:
plot(x, y1)
par(new = TRUE)
plot(x, y2, col = "red",
axes = FALSE,
xlab = '', ylab = '',
xlim = c(0, 10), ylim = c(min(y2), max(y1)))
but it did not work. Can someone please tell me how to fix this? (I am working with R for my code)
Many thanks in advance
How about
plot(x,y1, ylim=range(y1,y2), type="l")
lines(x, y2, col="red")
I would suggest trying to avoid multiple calls to plot with par(new=TRUE). That is usually very messy. Here we use lines() to add to an existing plot. The only catch is that the x and y limits won't change based on the new data, so we use ylim in the first plot() call to set a range appropriate for all the data.
Or if you don't want to worry about limits (like MrFlick mentioned) or the number of lines, you could also tide up your data and using melt and ggplot
df <- data.frame(x, y1, y2)
library(reshape2)
library(ggplot2)
mdf <- melt(df, "x")
ggplot(mdf, aes(x, value, color = variable)) +
geom_line()

Controlling z labels in contourplot

I am trying to control how many z labels should be written in my contour plot plotted with contourplot() from the lattice library.
I have 30 contour lines but I only want the first 5 to be labelled. I tried a bunch of things like
contourplot(z ~ z+y, data=d3, cuts=30, font=3, xlab="x axis", ylab="y axis", scales=list(at=seq(2,10,by=2)))
contourplot(z ~ z+y, data=d3, cuts=30, font=3, xlab="x axis", ylab="y axis", at=seq(2,10,by=2))
but nothing works.
Also, is it possible to plot two contourplot() on the same graph? I tried
contourplot(z ~ z+y, data=d3, cuts=30)
par(new=T)
contourplot(z ~ z+y, data=d3, cuts=20)
but it's not working.
Thanks!
Here is my take:
library(lattice)
x <- rep(seq(-1.5,1.5,length=50),50)
y <- rep(seq(-1.5,1.5,length=50),rep(50,50))
z <- exp(-(x^2+y^2+x*y))
# here is default plot
lp1 <- contourplot(z~x*y)
# here is an enhanced one
my.panel <- function(at, labels, ...) {
# draw odd and even contour lines with or without labels
panel.contourplot(..., at=at[seq(1, length(at), 2)], col="blue", lty=2)
panel.contourplot(..., at=at[seq(2, length(at), 2)], col="red",
labels=as.character(at[seq(2, length(at), 2)]))
}
lp2 <- contourplot(z~x*y, panel=my.panel, at=seq(0.2, 0.8, by=0.2))
lp3 <- update(lp2, at=seq(0.2,0.8,by=0.1))
lp4 <- update(lp3, lwd=2, label.style="align")
library(gridExtra)
grid.arrange(lp1, lp2, lp3, lp4)
You can adapt the custom panel function to best suit your needs (e.g. other scale for leveling the z-axis, color, etc.).
You can specify the labels as a character vector argument and set the last values with rep("", 5), so perhaps for the example you offered on an earlier question about contour
x = seq(0, 10, by = 0.5)
y = seq(0, 10, by = 0.5)
z <- outer(x, y)
d3 <- expand.grid(x=x,y=y); d3$z <- as.vector(z)
contourplot(z~x+y, data=d3)
# labeled '5'-'90'
contourplot(z~x+y, data=d3,
at=seq(5,90, by=5),
labels=c(seq(5,25, by=5),rep("", 16) ),
main="Labels only at the first 5 contour lines")
# contourplot seems to ignore 'extra' labels
# c() will coerce the 'numeric' elements to 'character' if any others are 'character'
?contourplot # and follow the link in the info about labels to ?panel.levelplot

Resources