I'm having trouble getting polygon() to shade below the distribution all the way to the x-axis. It seems to shade above the exponential distribution to a y=-x line. Here is where what I have so far:
x <- seq(0,50,0.01)
y <- dexp(seq(0,50,0.01),rate=0.11)
plot(x, y, type="l", col=col2rgb("yellow",0.5), xaxs="i", yaxs="i", ylim=c(0,0.15))
polygon(x, y ,border=NA,col=col2rgb("yellow",0.5))
Thanks so much!
Solution is simple, by adding (0,0) to the vertices of the polygon. See below:
x <- seq(0,50,0.01)
y <- dexp(seq(0,50,0.01),rate=0.11)
plot(x, y, type="l", col=col2rgb("yellow",0.5), xaxs="i", yaxs="i", ylim=c(0,0.15))
polygon(c(0, x), c(0, y), border=NA, col=col2rgb("yellow",0.5))
How polygon() works
polygon() will line up all vertices in order. The problem of your original code is that the origin (0, 0) is not one of the vertices, so it will not be part of the polygon. You can also consider the following toy example:
x0 <- c(0, 0.5, 1.5)
y0 <- c(1.5, 0.5, 0)
## triangle, with three vertices
plot(x0, y0, pch = ".")
polygon(x0, y0, col = "red", border = NA)
## area under triangle, four vertices
polygon(c(0, x0), c(0, y0), col = "yellow", border = NA)
Related
I am trying to draw some half circles on a plot, using the trigonometric functions in R.
So here is what I have :
matPoints <<- as.data.frame(cbind(X=c(-1, -(sqrt(3)/2), -(sqrt(2)/2), -0.5, 0, 0.5, sqrt(2)/2, sqrt(3)/2, 1), Y=c(0, 0.5, sqrt(2)/2, sqrt(3)/2, 1, sqrt(3)/2, sqrt(2)/2, 0.5, 0)))
plot(x = matPoints$X*W, y = matPoints$Y*W)
For the moment, it prints each point on the plot. What I want to do here is to trace a smooth line between points so it gives me a beautiful half circle of center (0, 0) and of scale W.
Any solution?
Do you mean this?
x <- seq(0, pi, length.out = 500)
W <- 3
plot(cos(x) * W, sin(x) * W, type = "l")
Since the general equation of a circle is x^2 + y^2 = r^2, you can mimic it like below as well,
r=3 # radius
x <- seq(-r,r,0.01)
y <- sqrt(r^2 - x^2)
plot(x,y,type="l")
# plot(c(x,x),c(y,-y),type="l") for a full circle.
gives,
Here's another possibility using complex numbers, and polygon to draw a closed shape.
plot(NA, xlim=c(-2,2), ylim=c(-2,2))
polygon(1i^(seq(0,2,l=100)))
Using this method you can easily change the centre, scale, rotation, fill colour etc:
plot(NA, xlim=c(-2,2), ylim=c(-2,2))
polygon(2*(1i^(seq(0,2,l=100)))*1i^.5 + .1-.3i, col="red")
polygon(1i^(seq(0,2,l=100)), col="blue")
I would like to use the function abline to plot several lines which should be made transparent but I am stuck.
Currently I have this code:
plot(x=NA, type="n", ylim=c(1, 9), xlim=c(1, 4), xlab="x-value",
ylab="y-value", cex.axis = 1, cex.lab = 1)
for (i in 1:nrow(one_hundred_regressions)) {abline(coef=one_hundred_regressions[i,],
col = "red")}
Use adjustcolor changing the alpha value to whatever degree of transparency you want:
plot(1:10)
abline(v = 1:10, col = adjustcolor("red", alpha = 0.3))
You may use RGB colors "#RRGGBBaa", where aa is the alpha value for transparency. Example:
plot(1:10, type="n")
Map(function(x, y, z) abline(coef=c(x, y), col=z, lwd=2), 2:4, 2/(2:4)^2,
c("#AA000066", "#00AA0066", "#0000AA66"))
I draw the graph below using the plot3D package of R. I would like to move a bit the z-axis label ($ f (y1, y2)) off the axis values or leave it in horizontal. Does anyone know how I can proceed? Next the code:
library("plot3D")
#Function density probability
library(pbivnorm)
bsb <- function(t1,t2){
a1 <- sqrt(phi1/2)*(sqrt(((phi1+1)*t1)/(phi1*mu1))-sqrt(((phi1*mu1)/((phi1+1)*t1))))
a2 <- sqrt(phi2/2)*(sqrt(((phi2+1)*t2)/(phi2*mu2))-sqrt(((phi2*mu2)/((phi2+1)*t2))))
Phi2 <- pbivnorm(a1, a2, rho, recycle = TRUE)
b1 <- ((phi1+1)/(2*phi1*mu1))*sqrt(phi1/2)*(((phi1*mu1)/((phi1+1)*t1))^(1/2)+((phi1*mu1)/((phi1+1)*t1))^(3/2))
b2 <- ((phi2+1)/(2*phi2*mu2))*sqrt(phi2/2)*(((phi2*mu2)/((phi2+1)*t2))^(1/2)+((phi2*mu2)/((phi2+1)*t2))^(3/2))
fdp <- Phi2*b1*b2
return(fdp)
}
t1 <- seq(0.001,100,length=30)
t2 <- seq(0.001,20,length=40)
#Parameters
mu1=7
phi1=2
mu2=1
phi2=9
rho=0
z<-outer(t1,t2,bsb) # calculate density values
pmat=persp3D(t1, t2, z,
main="",xlab="$y_{1}$",ylab="$y_{2}$",zlab="$f(y_{1},y_{2})$",cex.axis=1,cex.lab=1,
col = "gray10",border = "gray40",
theta=50, phi=15,
expand=0.9,
d=2,
shade=0.3,
ticktype="detailed",
nticks=5,
facets=FALSE,contour = list(nlevels=10,col="gray35"), zlim= c(-0.1, 0.23), bty = "b2")
text(trans3d(0,7.3,0.173,pmat), "(b)",cex=1,col="black")
The picture looks like this:
I would like the following pictures:
The problem is with the sizing of your output window. If you use a larger one, the text will look better. For example, with a full screen window I get this from your original code:
You could also specify a lower dpi value when you open the window if your graphics device supports that. For example, if I use dev.new(dpi = 50) I get
I don't think there's a way to rotate labels in persp3D, but you can draw the plot with no label, then use text to add a label. You'll also need to increase the margin size on that side. For example,
par(mar = c(5.1, 9.1, 4.1, 2.1))
pmat <- persp3D(t1, t2, z, main="", xlab="$y_{1}$", ylab="$y_{2}$",
zlab="", cex.axis=1, cex.lab=1,
col = "gray10", border = "gray40",
theta=50, phi=15,
expand=0.9, d=2, shade=0.3,
ticktype="detailed", nticks=5,
facets=FALSE, contour = list(nlevels=10,col="gray35"),
zlim= c(-0.1, 0.23), bty = "b2")
text(trans3d(0,7.3,0.173,pmat), "(b)", cex=1, col="black")
text(trans3d(0,-3,0.05,pmat), label= "$f(y_{1},y_{2})$",
cex=1, col="black", xpd=NA, pos=2)
This gives me:
I'm having trouble getting polygon() to shade below the distribution all the way to the x-axis. It seems to shade above the exponential distribution to a y=-x line. Here is where what I have so far:
x <- seq(0,50,0.01)
y <- dexp(seq(0,50,0.01),rate=0.11)
plot(x, y, type="l", col=col2rgb("yellow",0.5), xaxs="i", yaxs="i", ylim=c(0,0.15))
polygon(x, y ,border=NA,col=col2rgb("yellow",0.5))
Thanks so much!
Solution is simple, by adding (0,0) to the vertices of the polygon. See below:
x <- seq(0,50,0.01)
y <- dexp(seq(0,50,0.01),rate=0.11)
plot(x, y, type="l", col=col2rgb("yellow",0.5), xaxs="i", yaxs="i", ylim=c(0,0.15))
polygon(c(0, x), c(0, y), border=NA, col=col2rgb("yellow",0.5))
How polygon() works
polygon() will line up all vertices in order. The problem of your original code is that the origin (0, 0) is not one of the vertices, so it will not be part of the polygon. You can also consider the following toy example:
x0 <- c(0, 0.5, 1.5)
y0 <- c(1.5, 0.5, 0)
## triangle, with three vertices
plot(x0, y0, pch = ".")
polygon(x0, y0, col = "red", border = NA)
## area under triangle, four vertices
polygon(c(0, x0), c(0, y0), col = "yellow", border = NA)
I have a plot with two logarithmic axes. I'd like to add a circle to a certain position of the plot. I tried to use plotrix, but this does not give options for "log-radius".
# data to plot
x = 10^(-1 * c(5:0))
y = x ^-1.5
#install.packages("plotrix", dependencies=T)
# use require() within functions
library("plotrix")
plot (x, y, log="xy", type="o")
draw.circle(x=1e-2, y=1e2, radius=1e1, col=2)
How can I add a circle to my log-log plot?
As krlmlr suggests, the easiest solution is to slightly modify plotrix::draw.circle(). The log-log coordinate system distorts coordinates of a circle given in the linear scale; to counteract that, you just need to exponentiate the calculated coordinates, as I've done in the lines marked with ## <- in the code below:
library("plotrix")
draw.circle.loglog <-
function (x, y, radius, nv = 100, border = NULL, col = NA, lty = 1,
lwd = 1)
{
xylim <- par("usr")
plotdim <- par("pin")
ymult <- (xylim[4] - xylim[3])/(xylim[2] - xylim[1]) * plotdim[1]/plotdim[2]
angle.inc <- 2 * pi/nv
angles <- seq(0, 2 * pi - angle.inc, by = angle.inc)
if (length(col) < length(radius))
col <- rep(col, length.out = length(radius))
for (circle in 1:length(radius)) {
xv <- exp(cos(angles) * log(radius[circle])) * x[circle] ## <-
yv <- exp(sin(angles) * ymult * log(radius[circle])) * y[circle] ## <-
polygon(xv, yv, border = border, col = col[circle], lty = lty,
lwd = lwd)
}
invisible(list(x = xv, y = yv))
}
# Try it out
x = 10^(-1 * c(5:0))
y = x ^-1.5
plot (x, y, log="xy", type="o")
draw.circle.loglog(x = c(1e-2, 1e-3, 1e-4), y = c(1e2, 1e6, 1e2),
radius = c(2,4,8), col = 1:3)
A work around would be to apply log10 explicitly.
plot (log10(x), log10(y), type="o")
draw.circle(x=log10(1e-2), y=log10(1e2), radius=log10(1e1), col=2)
Edit (using symbols):
plot (x, y, log="xy", type="o",xlim=c(1e-5,1), ylim=c(1,1e8))
par(new=T)
symbols(x=1e-2, y=1e2, circles=1e1, xlim=c(1e-5,1), ylim=c(1,1e8),
xaxt='n', yaxt='n', ann=F, log="xy")
The function draw.circle from the plotrix package looks like that on my system:
> draw.circle
function (x, y, radius, nv = 100, border = NULL, col = NA, lty = 1,
lwd = 1)
{
xylim <- par("usr")
plotdim <- par("pin")
ymult <- (xylim[4] - xylim[3])/(xylim[2] - xylim[1]) * plotdim[1]/plotdim[2]
angle.inc <- 2 * pi/nv
angles <- seq(0, 2 * pi - angle.inc, by = angle.inc)
if (length(col) < length(radius))
col <- rep(col, length.out = length(radius))
for (circle in 1:length(radius)) {
xv <- cos(angles) * radius[circle] + x
yv <- sin(angles) * radius[circle] * ymult + y
polygon(xv, yv, border = border, col = col[circle], lty = lty,
lwd = lwd)
}
invisible(list(x = xv, y = yv))
}
<environment: namespace:plotrix>
What happens here is essentially that the circle is approximated by a polygon of 100 vertices (parameter nv). You can do either of the following:
Create your own version of draw.circle that does the necessary coordinate transformation to "undo" the log transform of the axes.
The function invisibly returns the list of coordinates that are used for plotting.
(If you pass a vector as radius, then only the coordinates of the last circle are returned.) You might be able to apply a transform to those coordinates and call polygon on the result. Pass appropriate values for border, col, lty and/or lwd to hide the polygon drawn by the functions itself.
The first version sounds easier to me. Simply replace the + x by a * x, same for y, inside the for loop, and you're done. Equivalently, for the second version, you subtract x and then multiply by x each coordinate, same for y. EDIT: These transformations are slightly wrong, see Josh's answer for the correct ones.