So I am trying to add some graphs to my notes of different functions.
Below is a simple interest function that gives the accumulated value of 1$ at time t with interest rate i. When I plot it, the initial function avSimple(0.075,t) looks fine but the addition ploted lines from the lines command plots the lines red & blue lines one unit to the right.
But they should all have a common point at t = 0, AV = 1.
What is going on here? I'm fairly new to this so I hope this isn't a dumb question.
# AV Simple Interest
avSimple = function(i,t){
av = (1 + (i * t))
return(av)}
t = 0:50
plot(t,avSimple(0.075,t), type="l", main = "AV Simple Interest",
xlab = "Time", ylab = "AV") # This plots good
lines(avSimple(0.05,t), col = "red") #This is shifted to right
lines(avSimple(0.025,t), col = "blue") #This is also shifted right
When using lines you should specify both the x and y values. If you only specify one value, R will assume those are y values and will set x=seq_along(y) (which will start at 1). You should be doing
t = 0:50
plot(t,avSimple(0.075,t), type="l", main = "AV Simple Interest",
xlab = "Time", ylab = "AV") # This plots good
lines(t, avSimple(0.05,t), col = "red") #This is shifted to right
lines(t, avSimple(0.025,t), col = "blue")
Related
I have this plot that it's creating me some problems as I don't manage to plot the red line between CIs. This plot is the fifth of a series of plots that are identical in nature and code. Only in this case, the line doesn't show up. I can't figure it out why.
This is my dataset and code:
ap_pp = structure(list(appp = c(0.0534256470459521, 0.318338283911788,
0.510498594892796, 0.659918013907143, 0.847855923395071, 1.33512933449448,
1.79114871626335), LB_T = c(-0.0039953960988687, -0.00128119112255898,
1.231602663197e-05, 0.000409544070864543, 0.00117091129359269,
0.00719127778296817, 0.0141800410470155), UB_T = c(0.00506390903978775,
0.00764795680079474, 0.010197655871224, 0.0127888162072783, 0.0157862071743087,
0.0195113089069214, 0.0216429332782514), LB_T = c(-0.0039953960988687,
-0.00128119112255898, 1.231602663197e-05, 0.000409544070864543,
0.00117091129359269, 0.00719127778296817, 0.0141800410470155),
UB_T = c(0.00506390903978775, 0.00764795680079474, 0.010197655871224,
0.0127888162072783, 0.0157862071743087, 0.0195113089069214,
0.0216429332782514)), class = "data.frame", row.names = c(NA,
-7L))
plot(ap_pp$appp, ylim = range(c(ap_pp$LB_T, appp$UB_T)), xlab = "", ylab = "", main = "LSAP", type = "n", xaxt = "n")
axis(1, at = 1:7, labels = load_unscaled_m$Date)
with(ap_pp, polygon(c(xx,rev(xx)),c(LB_T,rev(UB_T)), col = "#FFA6AA", border = FALSE))
abline(h = 0, col = "black", lty = 2)
lines(ap_pp$appp, type = "o", lwd = 2, col = "red")
Can anyone help me?
Thanks
You have some issues:
Typo, you use appp$UB_T in the range(), which doesn't exist. You need ap_pp$UB_T
Range. The line data you are trying to plot has a minimum of 0.05:
range(ap_pp$appp)
[1] 0.05342565 1.79114872
However, you set the y-axis to have a maximum of 0.02:
range(c(ap_pp$LB_T, ap_pp$UB_T))
[1] -0.003995396 0.021642933
Since the maximum of your y axis, 0.0216, is less than the minimum of the data you are plotting, 0.0534, all the points you are trying to plot are "above" the graph.
Graph type. You say "line", but by default plot will plot points. If you want a line, use type = "l". (Or lines(), as you do later.)
I have no idea what xx is, so I don't know what's going on with your polygon code. But presumably the y limits are again defined by UB_T and LB_T, and so the maximum of the y axis is still lower than the minimum of the data in lines()
Duplicate column names are a bad idea. You have two columns named LB_T and two named UB_T. They appear to be identical, which is less bad than if they were different, but I would strongly suggest not using duplicate column names so there is no ambiguity about which column you are referring to.
Perhaps you should include ap_pp$ppp in the range call.
I am trying to plot few graphs using loops. I am now describing in details.
First I have a function which is calculates the y-variable (called effect for vertical axis)
effect<- function (x, y){
exp(-0.35*log(x)
+0.17*log(y)
-0.36*sqrt(log(x)*log(y)/100))
}
Now I run the following code and use the option par to plot the lines in the same graph. I use axis=FALSE and xlab="" to get a plot without labels. I do this so that my labels are not re-written each time the loop runs and looks ugly.
for (levels in seq(exp(8), exp(10), length.out = 5)){
x = seq(exp(1),exp(10), length.out = 20)
prc= effect(levels,x)
plot(x, prc,xlim = c(0,max(x)*1.05), ylim=c(0.0,0.3),
type="o", xlab = "",ylab = "", pch = 16,
col = "dark blue", lwd = 2, cex = 1, axes = F)
label = as.integer(levels) #x variable
text(max(x)*1.03,max(prc), label )
par(new=TRUE)
}
Finally, I duplicate the plot command this time using the xlab and ylab options
plot(x, prc, xlab = "X-label", ylab = "effect",
xlim = c(0,max(x)*1.05), ylim = c(0,0.3),
type="l", col ='blue')
I have several other plots in the similar lines, using complex equations. I have two questions:
Is there an better option to have the same plot with smoother lines?
Is there an easier option with few lines to achieve the same, where I can place the texts (levels) for each line on the right with white background at the back?
I believe working with the plot function was tedious and time consuming. So, I have finally used ggplot2 to plot. There were several help available online, which I have used.
So I am trying to add some graphs to my notes. I have created a simple interest function that will plot several simple interest functions using different rates and I would like to add a legend that would simple say...
"i =: 0%, x%, y%, z%" on one single line, where each 0,x,y,z is in the different color of the representative function using that interest rate.
I looked into the paste() function and attempted to make it one string but I am not sure exactly how to loop it into the int_seq and pull out each individual index and make it a different color then put it into a single string.
# indexs to be used
t = 0:50
int_seq = seq(0.025,0.10,by=0.025) # intere rate sequence
colors = c("red","blue","green","orange") #colors of interest rate seq
index = 1:length(int_seq)
# AV Simple Interest (all good)
avSimple = function(i,t){
av = (1 + (i * t))
return(av)}
# Plot range for y-axis (all good)
yrange = c(avSimple(min(int_seq),min(t)) * 0.95,
avSimple(max(int_seq),max(t)) * 1.05)
# Plots Simple Interest with different interest rates (all good)
plot(t,avSimple(0,t), type="l", main = "AV Simple Interest", xlab = "Time",
ylab = "AV", ylim = yrange)
# loops through the int_seq and plots line based on interest rate
# and specified color (all good)
for (i in index)
lines(t,avSimple(int_seq[i],t), col = colors[i])
# Adds legend to plot for different interest rates
# !!This is where I need the help, not sure best way to approach!!
legend(0,avSimple(0.075,50), c("i =: 0%", for (i in index) int_seq[i]),
col = colors)
Not sure what kind of legend you want. Since you say in one line, you might want to add horiz = TRUE, but here are some other options:
You can pass full vectors to legend so there is no need for a loop in this case. Just create a vector of labels but also use a vector of colors corresponding to each label (which you have already done).
# indexs to be used
t = 0:50
int_seq = seq(0.025,0.10,by=0.025) # intere rate sequence
colors = c("red","blue","green","orange") #colors of interest rate seq
index = 1:length(int_seq)
# AV Simple Interest (all good)
avSimple = function(i,t){
av = (1 + (i * t))
return(av)}
# Plot range for y-axis (all good)
yrange = c(avSimple(min(int_seq),min(t)) * 0.95,
avSimple(max(int_seq),max(t)) * 1.05)
plot(t, type="n", main = "AV Simple Interest", xlab = "Time",
ylab = "AV", ylim = yrange)
# for (i in index)
# lines(t,avSimple(int_seq[i],t), col = colors[i])
# Adds legend to plot for different interest rates
# !!This is where I need the help, not sure best way to approach!!
labs <- sprintf('i =: %s%%', c(0, int_seq))
labs2 <- paste0(c(0, int_seq), '%')
legend('topleft', legend = labs, col = colors, lty = 1, title = 'normal')
l <- legend('top', legend = rep('i =:', length(labs)), lty = 1,
col = colors, text.width = max(strwidth(labs)) + 1,
title = 'right-justified')
text(l$rect$left + l$rect$w, l$text$y, labs2, pos = 2)
legend('topright', legend = labs, text.col = colors, title = 'colored')
legend('bottom', legend = labs, col = colors, lty = 1, horiz = TRUE,
cex = .7, title = 'horizontal')
I am quite new to R programming and have been given the task of representing some data in a boxplot. We were only provided the five figure summary of the data, i.e the lowest value, lower quartile,median,upper quartile,highest value. We are also told the amount of samples (n).
I read bxp was a function similar to boxplot but drew the boxplot based upon this five figure summary.
However, I know varwidth can be used to change the width of boxes proportionate to N, yet it does not seem to work here as all boxes are the same length. This is what I need help with.
MORSEYear1 <- c(18.2,58.5,64.4,73.4,91.1)
MORSEYear2 <- c(22.3,56.4,64.3,75.7,97.4)
MORSEYear3 <- c(29.1,57.9,66.6,73.4,86.0)
MathStatYear1 <- c(46.8,54.8,66.1,71.4,84.1)
MathStatYear2 <- c(35.1,47.8,57.8,65.7,82.8)
MathStatYear3 <- c(32.6,56.3,61.1,75.6,89.4)
MORSE1<-list(stats=matrix(MORSEYear1,MORSEYear1[5],MORSEYear1[1]), n=139)
MORSE2<-list(stats=matrix(MORSEYear2,MORSEYear2[5],MORSEYear2[1]), n=132)
MORSE3<-list(stats=matrix(MORSEYear3,MORSEYear3[5],MORSEYear3[1]), n=131)
MS1 <- list(stats=matrix(MathStatYear1,MathStatYear1[5],MathStatYear1[1]), n= 21)
MS2 <- list(stats=matrix(MathStatYear2,MathStatYear2[5],MathStatYear2[1]), n=20)
MS3 <- list(stats=matrix(MathStatYear3,MathStatYear3[5],MathStatYear3[1]), n= 14)
bxp(MORSE1, xlim = c(0.5,6.5),ylim = c(0,100),varwidth= TRUE, main = "Graph comparing distribution of marks across different years of MORSE and MathStat",ylab = "Marks", xlab = "Course and year of study (Course,Year)", axes = FALSE)
par(new=T)
bxp(MORSE2, xlim = c(-0.5,5.5), ylim = c(0,100),axes= TRUE, varwidth=TRUE)
par(new=T)
bxp(MORSE3, xlim = c(-1.5,4.5), ylim = c(0,100), varwidth=TRUE, axes = FALSE)
par(new=T)
bxp(MS1, xlim = c(-2.5,3.5), ylim = c(0,100), varwidth=TRUE, axes = FALSE)
par(new=T)
bxp(MS2, xlim = c(-3.5,2.5), ylim = c(0,100), varwidth=TRUE, axes = FALSE)
par(new=T)
bxp(MS3, xlim = c(-4.5,1.5), ylim = c(0,100), varwidth=TRUE, axes = FALSE)
NOTE: My supervisor said to use par(new=T) and change the xlim to plot multiple graphs using bxp(), if someone could verify if this is the best method or not that would be great!
Thanks
Stumbled upon the same problem, without much experience with R.
The varwidth argument of the bxp() function requires multiple boxplots being plotted at once. Adding to an initial plot does not count, as no readjustment is possible after the fact.
The question is how to construct a multidimensional z argument for bxp(). To answer this, a look at the result of something like boxplot(c(c(1,1),c(2,2))~c(c(11,11),c(22,22))) helps.
First, a generic example with made-up data to aid anyone that lands here:
# data
d1 <- c(1,2,3,4,5)
d2 <- c(1,2,3,5,8,13,21,34)
# summaries (generated with quantile and structured accordingly)
z1 <- list(
stats=matrix(quantile(d1, c(0.05,0.25,0.5,0.75,0.85))),
n=length(d1)
)
z2 <- list(
stats=matrix(quantile(d2, c(0.05,0.25,0.5,0.75,0.85))),
n=length(d2)
)
# merging the summaries appropriately
z <- list(
stats=cbind(z1$stats,z2$stats),
n=c(z1$n,z2$n)
)
# check result
print(z)
# call bxp with needed parameters ("at" can/should also be used here)
bxp(z=z,varwidth=TRUE)
In the case of the original question, one should merge MORSE# and MS#. The code is far from optimal - there might be a better way to merge and a function for this can be written, but the aim is ugly clarity and simplicity:
z <- list(
stats=cbind(MORSE1$stats, MORSE2$stats, MORSE3$stats, M1$stats, M2$stats, M3$stats),
n=c(MORSE1$stats, MORSE2$n, MORSE3$n, M1$n, M2$n, M3$n)
)
My code is below
data <-read.csv("Results_15Jan2015.csv")
PartNo <- data$PartNo
TotalTime <- data$TOTAL_TIME
mp <- barplot(height = TotalTime, main = "Plot of Total Time for different Part Numbers", xlab = "Different Part Numbers", ylab = "Total Time (sec)", xlim = c(1,42), ylim = c(0,max(TotalTime)+30),
col = rainbow(nrow(data)))
text(mp, par("usr")[3], labels = PartNo, srt = 45, adj = c(1.1,1.1), xpd = TRUE, cex=.9)
abline(h=mean(TotalTime))
specify_decimal <- function(x, k) format(round(x, k), nsmall=k)
text(7.5,mean(TotalTime)+25, paste("Average =",specify_decimal(mean(TotalTime),3)))
2 Questions:
a) Why is my horizontal line not drawn all the way to the right of the plot? How to draw the horizontal line all the way to the right?
b) I have a total of 42 observations, see http://imgur.com/97qHaUq
but the total number of bars shown is only 37, why? See http://imgur.com/dGj3WOt
I need to display all 42 bars in a single plot. how do I do that? thanks
As MrGrumble said, dropping the xlim argument should solve both of your problems (the line and missing bars). It might not be straightforward what this argument does in barplot function, as you don't give x explicitly. See in this example:
x <-seq(15)
barplot(x,xlim=c(1,15))
abline(h=6)
Gives a graphic with issues similar to those you are having, whereas
x <-seq(15)
barplot(x)
abline(h=6)
Behaves "as expected"