How can I change the shape of specific points in an R plot? I have a plot with four points, and I would like to change the shape of two points (0, 0.4991) and (1, 1.2258)in the following plot:
x = c(0,0,1,1,1)
y = c(0.4991,1.1423,1.2258,1.158,0.5148)
dat<-cbind(x,y)
myTicks<-c(0,1)
plot(dat[,1],dat[,2], yaxt="n", xaxt="n", xlab="", ylab="")
abline(0.4991,0.7267)
abline(1.1423,0.0157)
abline(0.4991,0.0157,lty=2)
axis(side = 1, at = myTicks)
axis(side = 2, at = myTicks)
You can specify the shape with pch parameter, which accept vectors, for example
x = c(0,0,1,1,1)
y = c(0.4991,1.1423,1.2258,1.158,0.5148)
point_shape = c(10,15,10,15,15)
dat<-data.frame(x,y,point_shape)
myTicks<-c(0,1)
plot(dat[,1],dat[,2], yaxt="n", xaxt="n", xlab="", ylab="", pch = dat$point_shape)
abline(0.4991,0.7267)
abline(1.1423,0.0157)
abline(0.4991,0.0157,lty=2)
axis(side = 1, at = myTicks)
axis(side = 2, at = myTicks)
Related
In R is there a way to have titles for side 3 (top) = x2 and side 4 (right) = y2 like highlighted below?
Below is R code.
x<-1:4; y=x*x
plot(x, y, pch=18, col="red", type="b",
frame=FALSE, xaxt="n") # Remove x axis
axis(1, 1:4, LETTERS[1:4], col.axis="blue")
axis(3, col = "darkgreen", lty = 2, lwd = 0.5)
axis(4, col = "violet", col.axis = "dark violet", lwd = 2)
You can add labels to additional axes using mtext(). For the right y axis you will probably need to add extra space using par(mar = ...)
par(mar = c(5, 4, 4, 5)) # create extra space for label
plot(1:5)
axis(3)
axis(4)
mtext("top xaxis", side = 3, line = 2)
mtext("right y axis needs extra space", side = 4, line = 2)
Created on 2022-11-08 with reprex v2.0.2
I'm a relative beginner in R so please forgive me if it's a noob question.
So, is there a package which provides an easy interface to plot (real-real, mathematical) functions? I need coordinate axis with arrows (and their intersection should be (0;0)) and ticks, grid, etc. I want similar plots as in this document.
Background: now I create function plots with LaTeX's tikzpicture and axis but I'm using R to generate randomized exams since few months (R creates tex-files and include them into document) and would be nice if R can create similar plots (png, jpg), because axis in LaTeX is very slow.
Thanks!
I made you a little function for this
math_plot <- function(f, xlim = c(-2,2), ylim = c(-2,2),
xlab = "x", ylab = "f(x)", ax.ext = .02,
frame.plot = F, grid.tick = .1, ...){
curve(f, from = xlim[1], to = xlim[2], ylim = ylim,
axes = F, xlab = "", ylab = "",
frame.plot = frame.plot, ...)
# x-axis
axis(1, pos = 0)
arrows(x0 = xlim[2], x1 = xlim[2] + diff(xlim)*ax.ext, y0 = 0, length = .1)
mtext(text = xlab, side = 4, line = 0, las = 2, at = 0)
# y-axis
axis(2, pos = 0, las = 2)
arrows(y0 = ylim[2], y1 = ylim[2] + diff(ylim)*ax.ext, x0 = 0, length = .1)
mtext(text = ylab, side = 3, line = 0, at = 0)
grid(nx = diff(xlim)/grid.tick, ny = diff(ylim)/grid.tick)
}
# give it a function
math_plot(function(x) 3*x + 2 - 2*x^2, ylim = c(-2,4))
With R graphic tools such as arrows, points, abline, etc. you can draw practically anything.
Example
op <- par(mar=c(1, 1, 1, 1)) ## adjust outer margins
plot(x, y, type="n", axes=F, asp=1, xlab="", ylab="") ## asp=1 to maintain 1:1 aspect ratio
lines(x, y, lwd=2)
arrows(par()$usr[1], 0, par()$usr[2], length=.05) ## par()$usr helps to find xlim and ylim
arrows(0, par()$usr[3], 0, par()$usr[4], length=.05)
points((-5:5)*10, rep(0, 11), pch=3, cex=.6) ## pch=3 for crosses
points(rep(0, 11), (-5:5)*10, pch=3, cex=.6)
mtext("y", 3, -1, adj=.55, font=8)
mtext("x", 4, -1, padj=-1, las=2, font=8)
abline(h=(-5:5)*10, lty=3, col="gray")
abline(v=(-5:5)*10, lty=3, col="gray")
text(10, -4, "10", font=7, cex=.8)
text(-4, 10, "10", font=7, cex=.8)
par(op) ## reset par
Data
x <- (-10):10; y <- x^2 - 50
I would like to plot two sets of values (from different datasets but for the same countries) with two x axes for several countries in two loops using par(new=T). R however overlays the second set of data starting from the last country.
Here you can see the result
https://www.dropbox.com/s/9x0dn7oom5czpwm/Rplot02.jpg?dl=0
Here is my code as an example for 2 countries only (I have 28).
par(mfrow=c(2,2))
par(mar = c(5,5,5,5), cex.axis=1)
for (i in colnames(DPreachdifft[,2:3])) {
plot(DPreachdifft$Diff, DPreachdifft[[i]],
type="p",col="red", xaxt="n", yaxt="n",
ylim = range(c(-25, 25)),
xlim = rev(range(DPreachdifft$Diff)),
ylab="delay(+) or advance(-) in years", xlab=NA, pch=16,
main = i, adj=0)
axis(side = 1, at=ticks,labels=ticks)
axis(side = 2)
abline(h=0)
}
par(new=T)
for (i in colnames(NPreachdifft[,2:3])) {
plot(NPreachdifft$Diff1, NPreachdifft[[i]],
type="p",col="blue", xaxt="n", yaxt="n",
ylim = range(c(-40, 40)),
xlab=NA, ylab=NA, pch=16)
axis(side = 3, at=ticks1)
mtext(side = 1, text="difference in DP", line = 2, adj = 0.5)
mtext(side = 3, text="difference in NP", line = 2, adj = 0.5)
}
I am doing a plot with R, the code for stacked bar and axis 2 are simple, here is the code for line and axis 4:
lines(y,
theLineValues,
type = "o",
pch = 20,
lwd = 2,
cex = 1.2,
lty = 1,
col ="forestgreen")
axis(4,
at = getYaxis(0,1,0.01, 3), # function to get 3 values for axis
labels = getYaxis(0,1,0.01, 3),
col.axis= "forestgreen",
las = 1,
cex.axis= 0.7,
col = "forestgreen",
line = 0)
then I found the min and max value: 0.46, 0.68 , and want to use them as axis, so the changing of line can be seen more obviously(the red line).
labels = getYaxis(min(theLineValues),max(theLineValues),0.01,3),
How would I scale the 'theLineValues' to do this?
Thanks.
======================================================================
Update 1: the code for 'y':
y <- barplot(
combinedvalues, # it's list of 3-combined values.
col = c("slategray1","darkseagreen1","moccasin"),
beside = FALSE,
border = "grey80",
las = 1,
cex.axis= 1.0,
ann = FALSE,
ylim = c(0,1),
yaxt = "n")
======================================================================
Update 2: the combined values:
these values are in .csv file, and use the following to get the 'combinedvalues' and pass it to 'y':
rbind(csv$frame0,csv$frame1,csv$frame2)
# frame0+frame1+frame2 shoud be 1, theLineValues were calculated by some formulas.
the csv file:
frame0 frame1 frame2 theLineValues
------------------------------------------------------------
0.4460203874 0.2271394791 0.3268401336 0.4674583872
0.4473756948 0.2084173711 0.3442069341 0.4796977238
0.5296042291 0.1570493286 0.3133464423 0.570317484
0.5255498752 0.1234146373 0.3510354875 0.6095475721
0.5405768621 0.119299957 0.3401231808 0.6251561825
0.5657840709 0.0916650587 0.3425508703 0.6896446583
0.4826617968 0.0877739789 0.4295642243 0.6610089801
0.3588171226 0.122977733 0.5182051444 0.606129318
0.2608499204 0.1705417922 0.5686082874 0.595971676
0.2111782825 0.2040231107 0.5847986067 0.6057364576
0.1731616573 0.240909341 0.5859290016 0.6153720603
Thanks.
======================================================================
Update 3: the final plot:
Frames.txt is based on the three frame columns.
Data
frames <- read.table("/your-path/frames.txt",header=T,na.string="NA")
theLineValues<-c(0.4674583872, 0.4796977238, 0.570317484, 0.6095475721, 0.6251561825, 0.6896446583, 0.6610089801, 0.606129318, 0.595971676, 0.6057364576, 0.6153720603)
Plot
barplot(t(frames), , col = c("slategray1","darkseagreen1","moccasin"))
axis(2, ylim=c(0,1))
mtext("barplot values", side=2, line=2)
box()
par(new=TRUE)
plot(theLineValues, type = "l", pch = 20, xlab="", ylab="", col = "forestgreen", lwd=2, ylim=c(min(theLineValues), max(theLineValues)), axes=FALSE)
axis(4, ylim=c(min(theLineValues), max(theLineValues)))
mtext("lineValues", side=4, line=0.2)
box()
My problem concerns the making of a graph for a publication in R. I have used the plot function like follows:
plot(x=data$SL, y=data$BD, xlab = "SL (mm)", ylab = "BD (mm)", pch=data$pch)
SL ranges from 51.7 to 73.7 and BD from 13.5 to 20.4. Unfortunately I am not allowed to post images yet.
However, wanting to get rid of the box I used "axes=F". Problem now is lack of control over the axis function. I used:
axis(side=1, lwd=3, xpd=TRUE, at=c(min(data$SL):max(data$SL)))
axis(side=2, lwd=3, xpd=TRUE, at=c(min(data$BD):max(data$BD)))
Problem is that I can't manage to get the y- and x-axis to come together on the same point as in the plot with the box. How to let the x- and y- axis to touch each other?
Most likely setting xaxs = "i" and yaxs = "i" will help you getting the desired behaviour.
plot(c(1,2,3),c(2,4,6),axes=F,xaxs = "i",yaxs="i",xlim=c(0,3),ylim=c(0,6))
axis(side=1, lwd=3, xpd=TRUE, at=0:3)
axis(side=2, lwd=3, xpd=TRUE, at=seq(0,6,2))
Try box(bty='L') to draw only the left and bottom parts of the box. You could also just draw the lines yourself using lines, segments, or abline and using grconvertX and grconvertY functions to find the locations where to draw the lines.
I suggest that you follow the procedure you outlined and then use:
box(which = "plot", bty = "l")
e.g.:
plot.new()
plot.window(xlim = c(1, 18), ylim = c(2, 20))
points(1:18, 2:19, pch = 1, col = "#FF7F24", cex = 1.2)
lines(1:18, 2:19, col = "#FF7F24", lwd = 2)
axis(side = 1,
lwd = 0,
lwd.ticks = 1,
at = 1:18,
cex.axis = 0.9)
title(main = "Plot",
ylab = "Y-Axis")
legend("top",
legend = c("Legend"),
col = c("#FF7F24"),
text.col = c("#FF7F24"),
pch = 1,
bty = "n",
cex = 1.2)
axis(side = 2,
lwd = 0,
lwd.ticks = 1)
box(which = "plot", bty = "l")
You should pass the options lwd = 0 and lwd.ticks = 1 to your seperate axis() calls in order to prevent some parts of your axes to appear fatter than other parts of your axis because some get overlayed by your call to box() and some do not.
The solution of using box() at the end is, I think, more general in that you can use it when e.g. you cannot or do not want to pass bty = "l" in your plot.default or plot.window call.