I'm drawing a ROC curve and R is putting to much space between the curve and the plot border. I want values at x = 0 to touch the y-axis and points at y = 1 to touch the upper border of the plot.
This image shows exactly how I want it:
http://en.wikipedia.org/wiki/File:Roccurves.png
Anyone got any idea?
For base graphics, use the axis style parameters, xaxs and yaxs, to constrain the plotting limits to the of the data.
dfr <- data.frame(x = 0:1, y = 0:1)
par(xaxs = "i", yaxs = "i")
with(dfr, plot(x, y))
For lattice, you use the xlim and ylim parameters.
xyplot(y ~ x, dfr, xlim = range(dfr$x), ylim = range(dfr$y))
For ggplot2, use coord_cartesian.
ggplot(dfr, aes(x, y)) +
geom_point() +
coord_cartesian(xlim = range(dfr$x), ylim = range(dfr$y))
Related
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.
I am plotting some values of autocorrelation in a R:
plot(y=lag[2:N],x=1:(N-1), xlab="lag",ylab="Autocorrelation",ylim=c(-1,1), pch=16,col="red")
abline(h=0, col="black")
abline(h=up, col="blue")
abline(h=low, col="blue")
This is my code and this is what I got in R
However, I want something like the image below, where I connect the points with a red line to the horizontal line at 0.
Any idea how to do it?
You can add vertical lines with type = "h", and then add the points separately
plot(y=lag[2:N],x=1:(N-1), xlab="lag",ylab="Autocorrelation",ylim=c(-1,1), col="black", type = "h")
points(y=lag[2:N],x=1:(N-1), xlab="lag", ylim=c(-1,1), pch=16,col="red", type = "p")
If using ggplot this should do:
plot_df = data.frame(x = 1:20, y = rnorm(20))
ggplot(plot_df, aes(x, y, ymax = y, ymin = 0)) +
geom_pointrange(color = "red") +
geom_hline(yintercept = min(plot_df$y), color = "blue") +
geom_hline(yintercept = max(plot_df$y), color = "blue")
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))
I'm ploting a vector of 29 values in a plot using:
plot(0:29, v, type="o", main="Title of the plot")
I try to adjust the grid to be unit by unit using:
grid(31, lw=2)
The problem is that x axis first value (0 position) doesn't start at the begining of the graph and grid starts at the begining, so both elements aren't aligned.
How can solve this issue?
Use abline instead.
plot(0:10)
abline(h = 0:10)
abline(v = 0:10)
You can also force the exact x and y limits:
plot(0:10, 0:10, xlim = c(0,10), ylim = c(0, 10), xaxs = "i", yaxs = "i")
grid(10)
In general, using abline is easier and more robust. I also often plot with type = "n", add lines/whatever in the background, then add the points.
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()