I am pretty new to R and I managed to create a graph using 'plot' but I forgot error bars and I would like to add them without redoing the whole thing. Does someone know a shortcut?
I calculated the mean by hand because the data set was so small.
Here is the raw data I used and the code to make the graph. I suppose I will need to have R calculate the mean and standard error, but when I try I cant get the graph to look the same.
# Pnem mean occurence each year
Plot9Pn <- c(46, 33, 28)
Plot11Pn <- c(20, 18, 10)
Plot14Pn <- c(34, 28, 26)
Plot15Pn <- c(57, 33, 12)
# Pram mean occurence each year
Plot9Pr <- c(30, 46, 95)
Plot11Pr <- c(8, 11, 14)
Plot14Pr <- c(10, 46, 46)
Plot15Pr <- c(15, 37, 110)
#hand calculated means across plots for each year- to be used in line graph
# Pn2009 <- 39.25
# Pn2010 <- 30.5
# Pn2011 <- 19
# Pr2009 <- 15.75
# Pr2010 <- 35
# Pr2011 <- 66.25
# Define 2 vectors
Pn <- c(39.25, 30.5, 19)
Pr <- c(15.75, 35, 66.25)
g_range <- range(0, Pn,Pr)
plot(Pr, type="o", pch=1, lty=1, col="red", ylim=g_range,
axes=FALSE, ann=FALSE)
lines(Pn, type="o", pch=2, lty=1, col="blue", ylim=g_range,
axes=FALSE, ann=FALSE)
# Make x axis using 2009-2011 labels
axis(1, at=1:3, lab=c("2009","2010","2011"))
# Create a title with a red, bold/italic font
title(main="Mean Yearly Pathogen Levels in Pilarcitos ", col.main="red", font.main=4)
# Label the x and y axes with dark green text
title(xlab="Year", col.lab=rgb(0,0.5,0))
title(ylab="# Positive", col.lab=rgb(0,0.5,0))
# Make y axis with horizontal labels that display ticks at
# every 4 marks. 4*0:g_range[2] is equivalent to c(0,4,8,12).
axis(2, las=1, at=8*0:g_range[2])
# Create box around plot
box()
# Create a legend at (1, g_range[2]) that is slightly smaller
# (cex) and uses the same line colors and points used by
# the actual plots
legend(1, g_range[2], c("P.ramorum","P. nemorosa"), cex=0.8,
col=c("red","blue"), pch=1:2, lty=1);
box()
I think you may have miscalculated the mean of Pn2010.
But if you also hand calculate the standard deviations
Pr.sd <- c(9.946, 16.553, 44.275)
Pn.sd <- c(15.903, 7.071, 9.309
You can add error bars with
arrows(x0=1:3, y0=Pr-Pr.sd, y1=Pr+Pr.sd,
code=3, angle=90, length=.1, col="red")
arrows(x0=1:3, y0=Pn-Pn.sd, y1=Pn+Pn.sd,
code=3, angle=90, length=.1, col="blue")
Here I just add +/- 1 sd. You can calculate them however you like. You might consider offsetting the points as it doesn't look particularly nice.
The arrows function is a base graphics function so it will work with the plotting code you already had. But to make things easier in the future, you'll probably want to look into use a plotting package like ggplot2 or lattice as both of those make plotting with multiple groups much easier and ggplot makes adding error bars easier as well.
Related
I'm trying to use R to do a barplot. Values I'm plotting range from 0 to 5.0, but are decimal values (such as 4.87) so I don't want to just use the default Y axis, because it just goes up in increments of 1.
I've created a custom Y axis, which works, but if I set the maximum value greater than about 4.5, it cuts off the tickmark at the top of the axis. This looks untidy so I want a way to ensure this tickmark will always appear, but I don't want to shorten my axis as it looks stupid if I do this.
My R code is as follows:
# Bar plot of mean SUS question scores
barplot(meanSUSQuestions$Mean,
main="Mean SUS Question Scores",
cex.main="0.8",
cex.axis="0.8",
cex.lab="0.8",
#names=c("q1", "q2", "q3","q4","q5","q6","q7","q8","q9","q10"),
names=c(1:10),
yaxt="n",
col="red")
axis(2, cex.axis="0.8", at=seq(0, 5, 0.5)) # Create custom Y axis
mtext(text="Mean Score", side=2, line=2, cex=0.8)
mtext(text="Question", side=1, line=2, cex=0.8)
The bar plot that this produces looks like this:
As you can see from the picture, the top tickmark is missing.
How can I get this top tickmark to appear?
barplot generates the image height based on the data. The range of your manual y-axis is considerably larger than the plot area and is thus cut off.
The easiest way to solve the issue in your specific case is to add an yaxp = c(0, 5, 11) to barplot instead of yaxt = "n" and axis.
A self-contained example:
# Bad
x <- 1:5
barplot(x, yaxt = "n") #, add = TRUE)
axis(2, at = seq(0, 6, 2)) # Create custom Y axis
# Good
barplot(x, yaxp = c(0, 6, 2))
I am a beginner with R. I managed to plot my data into overlapping histograms. However, I would like to place all the histograms on one page. I am struggling as I am not able to tell R, which sets to pick (only manage to plot one of the plots).
This is the code:
df<-read.csv("Salt dshalo sizes.csv",header=T)
#View(df)
library(ggplot2)
DSA<-df[,1]
DS1<-df[,2]
DSB<-df[,5]
DS2<-df[,6]
DSC<-df[,9]
DS3<-df[,10]
#remove the NA column by columns separately or it will chop the data
DSA=na.omit(DSA)
DS1=na.omit(DS1)
DSB=na.omit(DSB)
DS2=na.omit(DS2)
DSC=na.omit(DSC)
DS3=na.omit(DS3)
#plot histograms for DSA, DSB and DSC on one same graph
hist(DSA, prob=TRUE, main="Controls", xlab="Sizes (um)", ylab="Frequency", col="yellowgreen",xlim= c(5,25), ylim=c(0,0.5), breaks=10)
hist(DSB, prob=TRUE, col=rgb(0,0,1,0.5),add=T)
hist(DSC, prob=TRUE, col=rgb(0.8,0,1,0.5),add=T)
#add a legend to the histogram
legend("topright", c("Control 1", "Control2", "Control3"), text.width=c(1,1,1),lwd=c(2,2,2),
col=c(col="yellowgreen", col="blue", col="pink",cex= 1))
box()
#plot histograms for DS1, DS2 and DS3 on one same graph
hist(DS1, prob=TRUE, main="Monoculture Stressed", xlab="Sizes (um)", ylab="Frequency", col="yellowgreen",xlim= c(5,25), ylim=c(0,0.5), breaks=10)
hist(DS2, prob=TRUE, col=rgb(0,0,1,0.5),add=T)
hist(DS3, prob=TRUE, col=rgb(0.8,0,1,0.5),add=T)
#add a legend to the histogram
legend("topright", c("DS1", "DS2", "DS3"), text.width=c(1,1,1),lwd=c(2,2,2),
col=c(col="yellowgreen", col="blue", col="pink",cex= 1))
box()
# put both overlapping histograms onto one page
combined <- par(mfrow=c(1, 2))
plot(hist(DSA),main="Controls")
plot(hist(DS1),main="Monoculture stressed")
par(combined)
Basically, I get two separate overlapping histograms, but cannot put them on the same page.
EDIT: I evidently didn't read your question thoroughly. I see you figured out the add =T.
I assume what you are looking for then is the comment I made first:
par(mfrow = c(a,b)) where a and b are the number of rows and columns you want the graphics objects to be printed. I used c(2,2) for this pic.
I made a comment, but sounds like you may be talking about the add=T option.
a=rnorm(100, 2, 1)
b=rnorm(100, 4, 1)
hist(a, xlim=c(0,10), col="yellow")
hist(b, add=T, col="purple" )
you can play around with transparency options on colors to see both overlap. Such as rgb(1,0,0,1/4) as the color.
With transparency colors:
a=rnorm(100, 2, 1)
b=rnorm(100, 4, 1)
hist(a, xlim=c(0,10), col=rgb(1,1,0,1/4))
hist(b, add=T, col=rgb(1,0,0,1/4) )
I want to plot single bar in a graph so it would look like picture below
I created test data and calculate its mean.
value <- c(99,44,100,120,88)
value_mean <- mean(value)
And plot them using below code
barplot(value_mean, horiz=T, width=30, cex.names=0.5 ,ylim=c(0,200), col="red")
Buth the output is not even close.
I've also looked at this links
Single bar barchart in ggplot2, R
R Barplot with one bar - how to plot correctly
So my output should be something like the first picture. I was thinking that could solve ggplot.
If everything else fails, you can draw a rectangle like this:
par(mar = c(12, 2, 12, 2))
plot(0, type="n", ylim=c(-1, 1), xlim=c(0, 200), axes = F, bty = "n",ylab="", xlab="label")
rect(0, -.7, value_mean, .7, col="red", border=NA)
text(value_mean, 0, pos=4, label=value_mean)
axis(1, at=seq(0, 200, by=40))
I'am trying to plot 3 curve in the same plot, but I've got a problem with the third plot relying to bike, it doesn't appear :
Any idea please?
# Define 3 vectors
cars <- c(1, 3, 6, 4, 9)
trucks <- c(2, 5, 4, 5, 12)
bike <- c(12, 15, 14, 15, 12)
# Calculate range from 0 to max value of cars and trucks
g_range <- range(0, cars, trucks)
# Graph autos using y axis that ranges from 0 to max
# value in cars or trucks vector. Turn off axes and
# annotations (axis labels) so we can specify them ourself
plot(cars, type="o", col="blue", ylim=g_range,
axes=FALSE, ann=FALSE)
# Make x axis using Mon-Fri labels
axis(1, at=1:5, lab=c("Mon","Tue","Wed","Thu","Fri"))
Make y axis with horizontal labels that display ticks at every 4 marks. 4*0:g_range[2] is equivalent to c(0,4,8,12).
axis(2, las=1, at=4*0:g_range[2])
# Create box around plot
box()
# Graph trucks with red dashed line and square points
lines(trucks, type="o", pch=22, lty=2, col="red")
lines(bike, type="o", pch=23, lty=3, col="green")
# Create a title with a red, bold/italic font
title(main="Autos", col.main="red", font.main=4)
# Label the x and y axes with dark green text
title(xlab="Days", col.lab=rgb(0,0.5,0))
title(ylab="Total", col.lab=rgb(0,0.5,0))
c("cars","trucks"), cex=0.8, col=c("blue","red"), pch=21:22, lty=1:2);
You could use par(new=TRUE) then set the y-axis to the right side for the third graph.
x <- 1:5
y1 <- rnorm(5)
y2 <- rnorm(5,20)
par(mar=c(5,4,4,5)+.1)
plot(x,y1,type="l",col="red")
par(new=TRUE)
plot(x, y2,,type="l",col="blue",xaxt="n",yaxt="n",xlab="",ylab="")
axis(4)
mtext("y2",side=4,line=3)
legend("topleft",col=c("red","blue"),lty=1,legend=c("y1","y2"))
some sample graph from http://robjhyndman.com/hyndsight/r-graph-with-two-y-axes/
cheers,
Justin
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)