I'm unable to get the polygon to align with the curve. I'll put the code here:
critvalmax <- qt(0.975,df=4)
critvalmin <- qt(0.025,df=4)
xvals <- seq(-5, 5, length=100)
fx.samp.t <- dt(xvals, df=4)
plot(xvals, dnorm(xvals), col="white")
lines(xvals, fx.samp.t, lty=1, lwd=2)
abline(v= critvalmin, lty=2)
abline(v= critvalmax, lty=2)
abline(h=0, lty=3)
polygon(cbind(c(critvalmin, xvals[xvals>=critvalmin & xvals<=critvalmax], critvalmax, critvalmax), c(0, dt(critvalmin, df=4), fx.samp.t[xvals>=critvalmin & xvals<=critvalmax], 0)), density=10, lty=3)
The result is that the polygon is drawn a bit to the right and I can't find a solution by myself. Also, the left bottom corner doesn't seem to fill properly.
I removed some variables in your polygon like the second critvalmax and dt(critvalmin, df=4) and cbind. The dt(critvalmin, df=4) seems to have slightly moved your polygon by 0.02558082 to right. You can use the following code:
critvalmax <- qt(0.975,df=4)
critvalmin <- qt(0.025,df=4)
xvals <- seq(-5, 5, length=100)
fx.samp.t <- dt(xvals, df=4)
plot(xvals, dnorm(xvals), col="white")
lines(xvals, fx.samp.t, lty=1, lwd=2)
abline(v= critvalmin, lty=2)
abline(v= critvalmax, lty=2)
abline(h=0, lty=3)
polygon(c(critvalmin, xvals[xvals>=critvalmin & xvals<=critvalmax], critvalmax), c(0, fx.samp.t[xvals>=critvalmin & xvals<=critvalmax], 0), density=10, lty=3)
Created on 2022-08-31 with reprex v2.0.2
polygon only needs your x and y:
vectors containing the coordinates of the vertices of the polygon.
And the density:
the density of shading lines, in lines per inch. The default value of
NULL means that no shading lines are drawn. A zero value of density
means no shading nor filling whereas negative values and NA suppress
shading (and so allow color filling).
Related
I'm trying to reproduce the plot of the image using this code in R:
N = 1:100
r = 1
K = 1
r1 = list(r*N*(1 - (N/K)))
plot(N, r1[[1]])
but negative values appear on the graph. What am I doing wrong or how can I graph the image?
Thanks in advance
You could use the curve function, which is designed for drawing function curves. In this way, you avoid the detour of generating values in advance.
For the basic curve you just need to code your varying variable N as x:
curve(expr=r*x*(1 - (x/K)), from=1, to=100)
To completely reproduce the plot, we open the R graphics toolbox a little further.
op <- par(mar=c(4, 8, 2, 5)) ## set margins
curve(r*x*(1 - (x/K)), 1, 100,
xlab="", ylab="", xaxt="n", yaxt="n",
axes=FALSE, xaxs="i", yaxs="i",
ylim=c(-8e3, 3e3), lwd=2)
axis(2, labels=FALSE, lwd.ticks=0)
abline(h=-5e3)
text(max(N), -5e3*1.05, "N", font=8, xpd=TRUE)
mtext("r", 2, .5, at=0, las=1, font=8)
mtext("Growth rate", 2, .5, at=2e3, las=1, font=6, cex=1.5)
## for the "K" tick and label in the plot, we need to solve the equation
## to get the intersect with our abitrary x axis at -5e3
f <- function(x, y) r*x*(1 - (x/K)) - y
x.val <- uniroot(f, y=-5e3, lower=0, upper=1000)$root
## and insert the solution as x.value
axis(1, x.val, labels=FALSE, pos=-5e3)
text(x.val, -5e3*1.1, "K", font=8, xpd=TRUE)
par(op) ## reset margins
Result
If you have a look at r1, you'll see that the data are plotted correctly. The values begin at zero and decrease.
If you simply wanted to shift the data for a quick visualization, you can add a scale factor:
#add a scale factor - all values positive
r2<-r1[[1]]+10000
plot(N, r2)
or
#add a scale factor - span y = 0
r3<-r1[[1]]+5000
plot(N, r3)
Add annotation to the plot:
abline(h=0, col="black") #add line at zero
text(65, -600, "K", cex=1.5, col="black") #add text
I have two variables, x and y
x = runif(8, 0, runif(1, 1, 5))
y = x^2
that I want to plot. Note that the range of x (and hence y=x^2) is not always the same.
So, the command
plot(x, y, pch=19, col='red')
produces
However, I don't want the borders around the graph, so I use the bty='n' parameter for plot:
plot(x, y, pch=19, col='red', bty='n')
which produces
This is a bit unfortunate, imho, since I'd like the y-axis to go all the way up to 4 and the x-axis all the way to 2.
So, I ue the xaxp and yaxp parameters in the plot command:
plot(x, y, pch=19, col='red', bty='n',
xaxp=c(
floor (min(x)),
ceiling(max(x)),
5
),
yaxp=c(
floor (min(y)),
ceiling(max(y)),
5
)
)
which produces
This is a bit better, but it still doesn't show the full range. Also, I thought it nice that the default axis labaling uses steps that were like 1,2,3,4 or 0.5,1,1.5,2, not just some arbitrary fractions.
I guess R has some parameter or mechanism to plot the full range in the axis in a "humanly" fashion (0.5,1,1.5 ...) but I didn't find it. So, what could I try?
Try:
plot(x, y, pch=19, col='red', bty='n', xlim=c(min(x),max(x)),
ylim=c(min(y),max(y)), axes=FALSE)
axis(1, at=seq(floor(min(x)), ceiling(max(x)), 0.5))
axis(2, at=seq(floor(min(y)), ceiling(max(y)), 0.5))
Or if you'd prefer to hard-code those axis ranges:
axis(1, at=seq(0, 2, 0.5))
axis(2, at=seq(0, 4, 0.5))
Is that what you were after?
The goal is to reproduce this Bid-Rent graph in R:
The challenge is to draw the projected circles. So far I got:
The 2D part is created by the R code below with the traditional graphic system in base R:
#Distance
X <- seq(0,7,1)
#Bid Rent Curves: Commercial, Industrial, Residential
com <- -5*X + 10
ind <- -2*X + 7
res <- -0.75*X + 4
graph <- plot(X, com, type="l", col="green", ylim=c(0,10), xlab="", ylab="", axes=FALSE)
lines(X, ind, col="red")
lines(X, res, col="blue")
abline(v=0, h=0)
segments(1,0, 1,5, lty=2)
segments(2.5,0, 2.5,2, lty=2)
title(main="Bid Rent Curves", sub="Alonso Model",
xlab="Distance from CBD", ylab="Rent per m2")
text(2.5,7.5, "Commercial", col="green")
text(3.5,4, "Industrial", col="red")
text(5.5,2, "Residential", col="blue")
(Detail: Why the curves do not respect the ylim = 0 ?)
How make the projection and draw the semi-circles?
It is not exactly a 3D plot. I have looked into plot3D and rgl. I am not sure which packages or strategy to use from here.
I'm taking you at your word that you want circles, so you need to push the plot area into the upper right corner:
outHalfCirc <- function(r,colr) {opar=par(xpd=TRUE, new=TRUE) #plot ouside plot area
polygon(x=seq(r,-r,by=-0.1),
y= -sqrt(r^2 - seq(r,-r,by=-0.1)^2) , # solve r^2 = x^2 +y^2 for y
xlim =c(0,7 ), ylim=c(0,10), col=colr, # need xlim and ylim to match base plot ranges
yaxs="i", yaxt="n", xaxs="i") # yaxis off; x and y axes meet at origin
par(opar)}
Then push plot up and to the right: This will draw a colored half-circles (largest first so they overlap) below the y=0 line.
png() # send to image file; not needed for testing
opar <- par(mar=c(15, 15, 2,2) ) # default units are in widths of text-"line".
# the margins start at lower, then clockwise
# run your code
outHalfCirc(5.5, "blue")
outHalfCirc(2.5, "red")
outHalfCirc(1, "green")
dev.off() # complete image production
par(opar) # different than the 'opar' inside the function
Voila! Although not really circles because the aspect ratio is not 1. That can be fixed (or you could set the xlim and ylim to be equal.
I need to break an axis from 0.5 to 1.5. My code is:
matplot( wxyz$days_until_last_pay, wxyz[,c(2,3,4,5)], type=c("b"), pch=1, col=1:4,
main="x![enter image description here][1]", cex.main=0.8)
legend("bottomright", inset=c(0,-0.57), fill=NULL,
legend = c("mean","median","max", "min"), col=1:4, pch=1, cex=0.8)
library("plotrix")
axis.break(axis=2,1,,2,style="zigzag", brw=0.03)
But I only get a line in it. This is not breaking the axis.
How can I solve this?
Thanks!
axis.break puts a break into an existing plot, so if the axis is not "broken" it will not work.
One suggestion is to make two plots on top of each other and set their ylim be so that there is a gap between 0.5 and 1.5, e.g.
## Some data, set.seed(1)
dat <- matrix(c(rnorm(50, 2, 0.1),
rnorm(50, 0.2, 0.05),
rnorm(50, 0.3, 0.05)),
byrow=FALSE, ncol=3)
## Split the device into two subplots
par(mfrow = c(2,1))
## Set the bottom margin of the top plot to 0.1
par(mar=c(0.1,4.1,4.1,2))
## Top plot (first column of the matrix)
plot(dat[,1], add=T, type="l", xaxt="n", ylab="", ylim=c(1.5, 2.5))
## Set the top margin of the bottom plot to 0.1
par(mar=c(5.1,4.1,0.1,2))
## Bottom plot
matplot(dat[,2:3], type="l", col=2:3, ylab="", ylim=c(0, 0.5))
This gives you something like:
I would like to add a curved line to fit the dark bars of this supply cost curve (like the red line that appears in image). The height of the dark bars represent the range in uncertainty in their costs (costrange). I am using fully transparent values (costtrans) to stack the bars above a certain level
This is my code:
costtrans<-c(10,10,20,28,30,37,50,50,55,66,67,70)
costrange<-c(15,30,50,21,50,20,30,40,45,29,30,20)
cost3<-table(costtrans,costrange)
cost3<-c(10,15,10,30,20,50,28,21,30,50,37,20,50,30,50,40,55,45,66,29,67,30,70,20)
costmat <- matrix(data=cost3,ncol=12,byrow=FALSE)
Dark <- rgb(99/255,99/255,99/250,1)
Transparent<-rgb(99/255,99/255,99/250,0)
production<-c(31.6,40.9,3.7,3.7,1,0.3,1.105,0.5,2.3,0.7,0.926,0.9)
par(xaxs='i',yaxs='i')
par(mar=c(4, 6, 4, 4))
barplot(costmat,production, space=0, main="Supply Curve", col=c(Transparent, Dark), border=NA, xlab="Quantity", xlim=c(0,100),ylim=c(0, 110), ylab="Supply Cost", las=1, bty="l", cex.lab=1.25,axes=FALSE)
axis(1, at=seq(0,100, by=5), las=1, cex.axis=1.25)
axis(2, at=seq(0,110, by=10), las=1, cex.axis=1.25)
Image to describe what I am looking for:
I guess it really depends how you want to calculate the line...
One first option would be:
# Save the barplot coordinates into a variable
bp <- barplot(costmat,production, space=0, main="Supply Curve",
col=c(Transparent, Dark), border=NA, xlab="Quantity",
xlim=c(0,100), ylim=c(0, 110), ylab="Supply Cost", las=1,
bty="l", cex.lab=1.25,axes=FALSE)
axis(1, at=seq(0,100, by=5), las=1, cex.axis=1.25)
axis(2, at=seq(0,110, by=10), las=1, cex.axis=1.25)
# Find the mean y value for each box
mean.cost <- (costmat[1,]+colSums(costmat))/2
# Add a line through the points
lines(bp, mean.cost, col="red", lwd=2)
Which gives
Now, you could do some smoother line, using some sort of regression
For instance, using a LOESS regression.
# Perform a LOESS regression
# To allow for extrapolation, you may want to add
# control = loess.control(surface = "direct")
model <- loess(mean.cost~bp, span=1)
# Predict values in the 0:100 range.
# Note that, unless you allow extrapolation (see above)
# by default only values in the range of the original data
# will be predicted.
pr <- predict(model, newdata=data.frame(bp=0:100))
lines(0:100, pr, col="red", lwd=2)