Here I have two vectors: "Pr" and "Z"
here is my code:
Z=seq(1,10,by=0.5)
Pr=lapply(Z,functionZ)
plot(Z,Pr,main="CAT Bond Price with increasing attachment points",xlab="Attachment Point",ylab="Price")
grid(nx = NULL, ny = NULL, col = "blue", lty = "dotted")
I want to select only two points in the plot, namely those where Z=5, and Z=7.5 and label them as "Class A" and "Class B" respectively. How can I do that?
To stick with your base R plotting, you can use the text function.
Since you do not provide your FunctionZ I just use some example. I placed the labels to the left of the points. Depending on the shape of your function, you may wish to adjust the pos argument to place them elsewhere.
Z=seq(1,10,by=0.5)
functionZ = function(x) x + sin(x)
Pr=lapply(Z,functionZ)
plot(Z,Pr,main="CAT Bond Price with increasing attachment points",
xlab="Attachment Point",ylab="Price")
grid(nx = NULL, ny = NULL, col = "blue", lty = "dotted")
text(x=c(5,7.5), y=functionZ(c(5,7.5)), labels= c("Class A", "Class B"), pos=2)
Your example is not reproducible, so I made up some random data and plotted with ggplot:
Z=seq(1,10,by=0.5)
Pr <- 1:19
L <- c("Point1", rep(NA, 17), "Point19")
df <- data.frame(Pr, Z, L)
library(ggplot2)
ggplot(aes(x=Pr, y=Z, label=L), data=df) +
geom_point() +
geom_label() +
xlab("Attachment Point") +
ylab("Price") +
ggtitle("CAT Bond Price with increasing attachment points") +
theme_classic()
You just define which ones you want to show labels for in a separate labels column and ggplot does the rest.
In your case, when you define L just do
L <- ifelse(Z==7, "Class A", ifelse(Z==7.5, "Class B", NA))
Related
I am trying to plot two or more lines on the same graph using a loop. My plot is a population dynamic in which I want to repeatedly change the value of the starting population but keep all other parameters the same. I want to plot the different outcomes on one graph. Can anyone help?
Try the following:
library(ggplot2)
MAX.Y<-30
# year<-0:30
year<-1:30
rlp<-0.1
lp<-rep(0,MAX.Y)
lp[1]<-4000
K<-4000000
for(n in 1: (MAX.Y-1)) {lp[n+1]<-lp[n]+(rlp)*(1-lp[n]/K)*lp[n]}
# plot(lp~year, xlab="Time (years)", ylab="Population size", main=c(paste("B) Anchovy population growth"), paste ("in less productive environment")), col="darkorchid", type="l", cex.main=1.0)
sp<-rep(0,MAX.Y)
sp[1]<-100000
for(n in 1: (MAX.Y-1)) {sp[n+1]<-sp[n]+(rlp)*(1-sp[n]/K)*sp[n]}
# lines(sp~year, type="l", col="black")
data = data.frame(year=year,lp=lp, sp=sp)
data = reshape2::melt(data, id.vars = 'year')
ggplot(data, aes(year, value, colour = variable))+
geom_line()+
labs(x = "Time (years)", y = "Population size",
title = "B) Anchovy population growth \n in less productive environment")+
theme_minimal()
Here is what I would do.
First, since the computations for lp and sp are the same, only the initial values change, create a function to do it.
f <- function(initial, MAX, rlp, K){
x <- numeric(MAX)
x[1] <- initial
for(i in seq_len(MAX - 1)) {
x[i + 1] <- x[i] + rlp*(1 - x[i]/K)*x[i]
}
x
}
Now sapply the function to a vector of initial values.
MAX.Y <- 30
rlp <- 0.1
year <- seq_len(MAX.Y)
K <- 4000000
InitialValues <- setNames(c(4000, 100000), c("lp", "sp"))
x <- sapply(InitialValues, f, MAX.Y, rlp, K)
And plot it with matlines. But for matlines to work the plot must be created with the custom title, axis limits, etc.
plot(1, type = "n",
xlim = range(year), ylim = range(x),
main = c(paste("B) Anchovy population growth"), paste ("in less productive environment")),
xlab = "Time (years)",
ylab = "Population size",
cex.main = 1.0,
col = c("darkorchid", "black"))
matlines(x, lty = "solid")
My current plot:
My desired plot (nevermind the variables s)
Specifically: explanatory variables on the bottom with an x-axis, response variables on the right, relative frequency and the y-axis on the left. I'll attach my R code below.
mosaictable <- matrix (c (3, 9, 22, 21), byrow = T, ncol = 2)
rownames (mosaictable) = c ("White", "Blue ")
colnames (mosaictable) = c ("Captured", "Not Captured")
mosaicplot ((mosaictable), sub = "Pigeon Color", ylab = "Relative frequency",
col = c ("firebrick", "goldenrod1"), font = 2, main = "Mosaic Plot of Pigeon Color and Their Capture Rate"
)
axis (1)
axis (4)
This particular flavor of mosaic display where you have a "dependent" variable on the y-axis and want to add corresponding annotation, is sometimes also called a "spine plot". R implements this in the spineplot() function. Also plot(y ~ x) internally calls spineplot() when both y and x are categorical.
In your case, spineplot() does almost everything you want automatically provided that you supply it with a nicely formatted "table" object:
tab <- as.table(matrix(c(3, 22, 9, 21), ncol = 2))
dimnames(tab) <- list(
"Pigeon Color" = c("White", "Blue"),
"Relative Frequency" = c("Captured", "Not Captured")
)
tab
## Relative Frequency
## Pigeon Color Captured Not Captured
## White 3 9
## Blue 22 21
And then you get:
spineplot(tab)
Personally, I would leave it at that. But if it is really important to switch the axis labels from left to right and vice versa, then you can do so by first suppressing axes = FALSE and then adding them manually afterwards. The coordinates for that need to be obtained from the marginal distribution of the first variable and the conditional distribution of the second variable given the first, respectively
x <- prop.table(margin.table(tab, 1))
y <- prop.table(tab, 1)[2, ]
spineplot(tab, col = c("firebrick", "goldenrod1"), axes = FALSE)
axis(1, at = c(0, x[1]) + x/2, labels = rownames(tab), tick = FALSE)
axis(2)
axis(4, at = c(0, y[1]) + y/2, labels = colnames(tab), tick = FALSE)
My current plot:
My desired plot (nevermind the variables s)
Specifically: explanatory variables on the bottom with an x-axis, response variables on the right, relative frequency and the y-axis on the left. I'll attach my R code below.
mosaictable <- matrix (c (3, 9, 22, 21), byrow = T, ncol = 2)
rownames (mosaictable) = c ("White", "Blue ")
colnames (mosaictable) = c ("Captured", "Not Captured")
mosaicplot ((mosaictable), sub = "Pigeon Color", ylab = "Relative frequency",
col = c ("firebrick", "goldenrod1"), font = 2, main = "Mosaic Plot of Pigeon Color and Their Capture Rate"
)
axis (1)
axis (4)
This particular flavor of mosaic display where you have a "dependent" variable on the y-axis and want to add corresponding annotation, is sometimes also called a "spine plot". R implements this in the spineplot() function. Also plot(y ~ x) internally calls spineplot() when both y and x are categorical.
In your case, spineplot() does almost everything you want automatically provided that you supply it with a nicely formatted "table" object:
tab <- as.table(matrix(c(3, 22, 9, 21), ncol = 2))
dimnames(tab) <- list(
"Pigeon Color" = c("White", "Blue"),
"Relative Frequency" = c("Captured", "Not Captured")
)
tab
## Relative Frequency
## Pigeon Color Captured Not Captured
## White 3 9
## Blue 22 21
And then you get:
spineplot(tab)
Personally, I would leave it at that. But if it is really important to switch the axis labels from left to right and vice versa, then you can do so by first suppressing axes = FALSE and then adding them manually afterwards. The coordinates for that need to be obtained from the marginal distribution of the first variable and the conditional distribution of the second variable given the first, respectively
x <- prop.table(margin.table(tab, 1))
y <- prop.table(tab, 1)[2, ]
spineplot(tab, col = c("firebrick", "goldenrod1"), axes = FALSE)
axis(1, at = c(0, x[1]) + x/2, labels = rownames(tab), tick = FALSE)
axis(2)
axis(4, at = c(0, y[1]) + y/2, labels = colnames(tab), tick = FALSE)
I am looking to plot the following:
L<-((2*pi*h*c^2)/l^5)*((1/(exp((h*c)/(l*k*T)-1))))
all variables except l are constant:
T<-6000
h<-6.626070040*10^-34
c<-2.99792458*10^8
k<-1.38064852*10^-23
l has a range of 20*10^-9 to 2000*10^-9.
I have tried l<-seq(20*10^-9,2000*10^-9,by=1*10^-9), however this does not give me the results I expect.
Is there a simple solution for this in R, or do I have to try in another language?
Thank you.
Looking at the spectral radiance equation wikipedia page, it seems that your formula is a bit off. Your formula multiplies an additional pi (not sure if intended) and the -1 is inside the exp instead of outside:
L <- ((2*pi*h*c^2)/l^5)*((1/(exp((h*c)/(l*k*T)-1))))
Below is the corrected formula. Also notice I have converted it into a function with parameter l since this is a variable:
T <- 6000 # Absolute temperature
h <- 6.626070040*10^-34 # Plank's constant
c <- 2.99792458*10^8 # Speed of light in the medium
k <- 1.38064852*10^-23 # Boltzmann constant
L <- function(l){((2*h*c^2)/l^5)*((1/(exp((h*c)/(l*k*T))-1)))}
# Plotting
plot(L, xlim = c(20*10^-9,2000*10^-9),
xlab = "Wavelength (nm)",
ylab = bquote("Spectral Radiance" ~(KW*sr^-1*m^-2*nm^-1)),
main = "Plank's Law",
xaxt = "n", yaxt = "n")
xtick <- seq(20*10^-9, 2000*10^-9,by=220*10^-9)
ytick <- seq(0, 4*10^13,by=5*10^12)
axis(side=1, at=xtick, labels = (1*10^9)*seq(20*10^-9,2000*10^-9,by=220*10^-9))
axis(side=2, at=ytick, labels = (1*10^-12)*seq(0, 4*10^13,by=5*10^12))
The plot above is not bad, but I think we can do better with ggplot2:
h <- 6.626070040*10^-34 # Plank's constant
c <- 2.99792458*10^8 # Speed of light in the medium
k <- 1.38064852*10^-23 # Boltzmann constant
L2 <- function(l, T){((2*h*c^2)/l^5)*((1/(exp((h*c)/(l*k*T))-1)))} # Plank's Law
classical_L <- function(l, T){(2*c*k*T)/l^4} # Rayleigh-Jeans Law
library(ggplot2)
ggplot(data.frame(l = c(20*10^-9,2000*10^-9)), aes(l)) +
geom_rect(aes(xmin=390*10^-9, xmax=700*10^-9, ymin=0, ymax=Inf),
alpha = 0.3, fill = "lightblue") +
stat_function(fun=L2, color = "red", size = 1, args = list(T = 3000)) +
stat_function(fun=L2, color = "green", size = 1, args = list(T = 4000)) +
stat_function(fun=L2, color = "blue", size = 1, args = list(T = 5000)) +
stat_function(fun=L2, color = "purple", size = 1, args = list(T = 6000)) +
stat_function(fun=classical_L, color = "black", size = 1, args = list(T = 5000)) +
theme_bw() +
scale_x_continuous(breaks = seq(20*10^-9, 2000*10^-9,by=220*10^-9),
labels = (1*10^9)*seq(20*10^-9,2000*10^-9,by=220*10^-9),
sec.axis = dup_axis(labels = (1*10^6)*seq(20*10^-9,2000*10^-9,by=220*10^-9),
name = "Wavelength (\U003BCm)")) +
scale_y_continuous(breaks = seq(0, 4*10^13,by=5*10^12),
labels = (1*10^-12)*seq(0, 4*10^13,by=5*10^12),
limits = c(0, 3.5*10^13)) +
labs(title = "Black Body Radiation described by Plank's Law",
x = "Wavelength (nm)",
y = expression("Spectral Radiance" ~(kWsr^-1*m^-2*nm^-1)),
caption = expression(''^'\U02020' ~'Spectral Radiance described by Rayleigh-Jeans Law, which demonstrates the ultraviolet catastrophe.')) +
annotate("text",
x = c(640*10^-9, 640*10^-9, 640*10^-9, 640*10^-9,
150*10^-9, (((700-390)/2)+390)*10^-9, 1340*10^-9),
y = c(2*10^12, 5*10^12, 14*10^12, 31*10^12,
35*10^12, 35*10^12, 35*10^12),
label = c("3000 K", "4000 K", "5000 K", "6000 K",
"UV", "VISIBLE", "INFRARED"),
color = c(rep("black", 4), "purple", "blue", "red"),
alpha = c(rep(1, 4), rep(0.6, 3)),
size = 4.5) +
annotate("text", x = 1350*10^-9, y = 23*10^12,
label = deparse(bquote("Classical theory (5000 K)"^"\U02020")),
color = "black", parse = TRUE)
Notes:
I created L2 by also making absolute temperature T a variable
For each T, I plot the function L2 using different colors for representation. I've also added a classical_L function to demonstrate classical theory of spectral radiance
geom_rect creates the light blue shaded area for "VISIBLE" light wavelength range
scale_x_continuous sets the breaks of the x axis, while labels sets the axis tick labels. Notice I have multiplied the seq by (1*10^9) to convert the units to nanometer (nm). A second x-axis is added to display the micrometer scale
Analogously, scale_y_continuous sets the breaks and tick labels for y axis. Here I multiplied by (1*10^-12) or (1*10^(-3-9)) to convert from watts (W) to kilowatts (kW), and from inverse meter (m^-1) to inverse nanometer (nm^-1)
bquote displays superscripts correctly in the y axis label
annotate sets the coordinates and text for curve labels. I've also added the labels for "UV", "VISIBLE" and "INFRARED" light wavelengths
ggplot2
Plot from wikipedia:
Image source: https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Black_body.svg/600px-Black_body.svg.png
I want to create one plot graph with the Roundrobin and Prediction points, without colors, where the Roundrobin and Prediction type of points are different, and it has a legend. I was want to add a best fit line for the results.
I am having trouble in adding all these features into one graph that has 2 points. I am used to Gnuplot, but I don't know how to do this with R. How I do this with R?
[1] Input data
Inputdata,Roundrobin,Prediction
1,178,188
2,159,185
3,140,175
[2] Script to generate data
no_faults_data <- read.csv("testresults.csv", header=TRUE, sep=",")
# Graph 1
plot(no_faults_data$Inputdata, no_faults_data$Roundrobin,ylim = range(c(no_faults_data$Roundrobin,no_faults_data$Prediction)),xlab="Input data size (MB)", ylab="Makespan (seconds)")
points(no_faults_data$Inputdata, no_faults_data$Prediction)
abline(no_faults_data$Inputdata, no_faults_data$Roundrobin, untf = FALSE, \dots)
abline(no_faults_data$Inputdata, no_faults_data$Prediction, untf = FALSE, \dots)
legend("top", notitle, c("Round-robin","Prediction"), fill=terrain.colors(2), horiz=TRUE)
In base R you will have to create a fitted model first:
robin <- lm(Roundrobin ~ Inputdata, data = no_faults_data)
pred <- lm(Prediction ~ Inputdata, data = no_faults_data)
plot(no_faults_data$Inputdata, no_faults_data$Roundrobin,
ylim = range(c(no_faults_data$Roundrobin,no_faults_data$Prediction)),
xlab = "Input data size (MB)", ylab = "Makespan (seconds)",
col = "green", pch = 19, cex = 1.5)
points(no_faults_data$Inputdata, no_faults_data$Prediction, pch = 22, cex = 1.5)
abline(robin, lty = 1)
abline(pred, lty = 5)
legend(1.1, 155, legend = c("Round-robin","Prediction"), pch = c(19,22), col = c("green","black"),
bty = "n", cex = 1.2)
which gives:
For further customization of the base R plot, see ?par and ?legend.
With ggplot2 you will need to reshape your data into long format:
library(reshape2)
library(ggplot2)
ggplot(melt(no_faults_data, id="Inputdata"),
aes(x=Inputdata, y=value, shape=variable, color=variable)) +
geom_point(size=4) +
geom_smooth(method = "lm", se = FALSE) +
theme_minimal()
which gives:
Used data:
no_faults_data <- read.csv(text="Inputdata,Roundrobin,Prediction
1,178,188
2,159,185
3,140,175", header=TRUE)
You should look into the ggplot2 package for plotting. Maybe not needed for the 3 points data you provided but it makes much nicer plots than the default.
df <- data.frame("Inputdata" = c(1,2,3,1,2,3), "score" = c(178,159,140,188,185,175), "scoreType" = c(rep("Roundrobin",3), rep("Prediction",3)))
p <- ggplot(data=df, aes(x=Inputdata, y=score, group=scoreType, shape = scoreType)) + geom_point(size=5)
p <- p + ggtitle("My Title")
p+stat_smooth(method="lm",se = FALSE)
Here you group by the type of score and let GG plot make the legend for you. stat_smooth is using lm here.