I can't add axis() to plot when using abline(lm()), why? - r

I am struggling because I am just trying to add my own x-axis values and tickmarks to a plot which shows also the linear regression.
It seems that OR I add the abline OR I add the axis. I can't do both!
Why?
Example data:
df = data.frame(year = c(1901:2000), total = ceiling(runif(100, 2, 3000)))
This code works ONLY for abline():
plot(df$year, df$total, xaxt='n')
abline(lm(df$total ~ df$year))
axis(1, at = seq(1,100, by = 10), labels = seq(1901, 2000, by = 10)) #this line does not work
This code works only for axis():
plot(df$total, xaxt='n')
abline(lm(df$total ~ df$year)) #this line does not work
axis(1, at = seq(1,100, by = 10), labels = seq(1901, 2000, by = 10))
Any help, please?
thank you

The x-axis does not necessarily go from 1 to 100. The units are defined by the scale of your variable.
In your first example, the x-axis actually goes from 1901 to 2000. You therefore need to define at in that range, otherwise your values fall outside the plot and are invisible. Simply do:
plot(df$year, df$total, xaxt='n')
abline(lm(df$total ~ df$year))
axis(1, at = seq(1901, 2000, by = 10))
The second example your axis call works because you are plotting index on the x-axis, which just counts from 1 to n observations (in this case 100). The abline is not visible, since it is not within the range of that plot.

Related

Change x-axis intervals to be monthly in r

I have a data frame with the first column named "Date." It has values like "2016-01-01, 2016-01-02 ..." etc. The second column is named "precipBulk," and it just has decimal values (ex. 3.36, 1.57, etc.). The third column is named "abundance," and it also has decimal values. I want to graph both "abundance" and "precipBulk" on one graph(Like the image), but I want the x-axis to have intervals with every month instead of every other month like it is now. I know there's a way to do it in ggplot2 using "scale_x_date()" but I can't graph both of the y values in one graph with ggplot2 for some reason. Is there a way to do it without using ggplot2? if not, any tips on how I would graph dual y-axis to achieve this with ggplot2?
Graph link https://i.stack.imgur.com/SZXgT.png `
Small portion of data frame https://i.stack.imgur.com/PvTED.png
To make the graph, I did:
x = frame$Date
y1 = frame$precipBulk
y2 = frame$abundance
plot(x,y1, type = "l",ylab="Bulk Precipitation",xlab="Month",col="blue", main = "Precipitation vs Mosquito Abundance (OSBS 2016)", cex.main = 1)
par(new = TRUE)
plot(x, y2, type = "l",yaxt="n",xaxt="n",ylab="",col="red")
axis(side = 4)
legend('topleft', c("Precipitation", "Mosquito Abundance"), col= c("blue", "Red"),lty=c(1,1), adj = c(0,0.6), cex= 0.75)
You need to turn the x-axis off (as you did) and then add it manually, perhaps reducing the size if necessary so that the axis tick labels fit, otherwise, R will decide for you.
x <- seq(as.Date("2017-01-01"), as.Date("2018-01-01"), "day")
plot(x, rnorm(length(x)), xaxt="n")
at <- seq(min(x), max(x), "month")
axis(side=1, at=at, labels=format(at, "%b"), cex.axis=0.7)

R Barplot: Y-axis cut off at the top?

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))

Twosided Barplot in R with different data

I was wondering if it's possible to get a two sided barplot (e.g. Two sided bar plot ordered by date) that shows above Data A and below Data B of each X-Value.
Data A would be for example the age of a person and Data B the size of the same person. The problem with this and the main difference to the examples above: A and B have obviously totally different units/ylims.
Example:
X = c("Anna","Manuel","Laura","Jeanne") # Name of the Person
A = c(12,18,22,10) # Age in years
B = c(112,186,165,120) # Size in cm
Any ideas how to solve this? I don't mind a horizontal or a vertical solution.
Thank you very much!
Here's code that gets you a solid draft of what I think you want using barplot from base R. I'm just making one series negative for the plotting, then manually setting the labels in axis to reference the original (positive) values. You have to make a choice about how to scale the two series so the comparison is still informative. I did that here by dividing height in cm by 10, which produces a range similar to the range for years.
# plot the first series, but manually set the range of the y-axis to set up the
# plotting of the other series. Set axes = FALSE so you can get the y-axis
# with labels you want in a later step.
barplot(A, ylim = c(-25, 25), axes = FALSE)
# plot the second series, making whatever transformations you need as you go. Use
# add = TRUE to add it to the first plot; use names.arg to get X as labels; and
# repeat axes = FALSE so you don't get an axis here, either.
barplot(-B/10, add = TRUE, names.arg = X, axes = FALSE)
# add a line for the x-axis if you want one
abline(h = 0)
# now add a y-axis with labels that makes sense. I set lwd = 0 so you just
# get the labels, no line.
axis(2, lwd = 0, tick = FALSE, at = seq(-20,20,5),
labels = c(rev(seq(0,200,50)), seq(5,20,5)), las = 2)
# now add y-axis labels
mtext("age (years)", 2, line = 3, at = 12.5)
mtext("height (cm)", 2, line = 3, at = -12.5)
Result with par(mai = c(0.5, 1, 0.25, 0.25)):

dates ticks and labels on x-axis of a time series

I am trying for the last few hours to get the ticks of desired dates with labels as Month-Year on the x-axis of a time series plot. I have tried tons of things available on Stack and others but none worked out so far.
Below is an example of what I am trying so far. I am getting plot with x-axis as a numeric such as 2014.0, while I want it to be in the date format such as Jan-2014.
I am also trying to learn, in case of numeric year labels, how can I start my x-axis with 2014.1 instead of 2014.0 as the first month of my series is January. To get this I tried time function with offset=1 but it didn't work either. Please check below example
## dataframe and its time series
temp_df<- data.frame(date_temp= as.Date(dates_of_data), opp_temp= rnorm(29,mean = 100,sd=5))
temp_ts<- ts(temp_df[,2], start=2014, freq=12)
## plot
plot(temp_ts, axes=F, lwd=3, ylim=c(min(temp_ts),max(temp_ts)), xlab="", ylab="",type="l",col="black", main="")
points(temp_ts,pch=20,col="yellow")
## y-axis
axis(2, ylim=c(min(temp_ts),max(temp_ts)),col="black",lwd=2,line=1)
mtext(2,text="Y-axis count",line=3,col="black")
## x-axis
axis(1,pretty(range(time(temp_ts)),12))
mtext("Time - Year",side=1,col="black",line=2, lwd=3)
## axis(1,pretty(range(time(temp_ts, offset=1)),12)) -- didnt work either
temp_dates<- as.Date(as.yearmon(time(temp_ts)))
axis(side=1, at=tt, labels = FALSE)
axis(side = 1, at = tt[ix], labels = labs[ix], tcl = -0.7, cex.axis = 1)
grid (NULL,NULL, lty = 6, col = "blue")
dev.off()
Couple of things that I have tried so far includes
# 1. par(xaxt="n") ## didn't work
# 2. axis(1, at=seq(from = min(temp_dates),to = max(temp_dates), by="month"), labels=format(temp_dates,"%Y-%b"),las=2)
Can you please tell me how to get x-axis labels as Jan-2014 (Month-Year)?
These are some of the link I went through as requested: here
here
here
here
and
here
EDIT: Below solution works perfectly using zoo library. However I have't been using zoo the whole time in my study and was interested more in doing the other way. Please correct what is wrong in the previous approach.
require(zoo)
dev.off()
x<- (zoo(temp_df$opp_temp, temp_df$date_temp))
plot(x, xaxt = "n")
x_times <- time(x)
ticks <- seq(x_times[1], x_times[length(x_times)], by = "month")
grid (5,5, lty = 6, col = "blue")
axis(1, at = ticks, labels = format(x_times,"%Y-%b"),las=2, tcl = -0.3)

Combining 2 datasets in a single plot in R

I have two columns of data, f.delta and g.delta that I would like to produce a scatter plot of in R.
Here is how I am doing it.
plot(f.delta~x, pch=20, col="blue")
points(g.delta~x, pch=20, col="red")
The problem is this: the values of f.delta vary from 0 to -7; the values of g.delta vary from 0 to 10.
When the plot is drawn, the y axis extends from 1 to -7. So while all the f.delta points are visible, any g.delta point that has y>1 is cut-off from view.
How do I stop R from automatically setting the ylims from the data values. Have tried, unsuccessfully, various combinations of yaxt, yaxp, ylims.
Any suggestion will be greatly appreciated.
Thanks,
Anjan
In addition to Gavin's excellent answer, I also thought I'd mention that another common idiom in these cases is to create an empty plot with the correct limits and then to fill it in using points, lines, etc.
Using Gavin's example data:
with(df,plot(range(x),range(f.delta,g.delta),type = "n"))
points(f.delta~x, data = df, pch=20, col="blue")
points(g.delta~x, data = df, pch=20, col="red")
The type = "n" causes plot to create only the empty plotting window, based on the range of x and y values we've supplied. Then we use points for both columns on this existing plot.
You need to tell R what the limits of the data are and pass that as argument ylim to plot() (note the argument is ylim not ylims!). Here is an example:
set.seed(1)
df <- data.frame(f.delta = runif(10, min = -7, max = 0),
g.delta = runif(10, min = 0, max = 10),
x = rnorm(10))
ylim <- with(df, range(f.delta, g.delta)) ## compute y axis limits
plot(f.delta ~ x, data = df, pch = 20, col = "blue", ylim = ylim)
points(g.delta ~ x, data = df, pch = 20, col = "red")
Which produces

Resources