How to fix the position of a text to follow an object plotted in R - r

I was wondering how I can fix a piece of text() to always appear above a bracket (or a points() etc.) in a dynamically changing plot? In other words, how should I determine the "x" and "y" for that piece of text to follow the bracket (or a points() etc.) around anywhere in the plot? (see my R code below)
Just as an example, suppose I have a bracket in the plot below whose position (xs and ys) is going to be always known regardless of how the plot will change. Here, how can I fix the position of the text() above this bracket (as currently seen in the plot) no matter where the bracket goes?
P.S. At first, I thought I can take the "y" of the bracket, and then make "y" of the text() to be: ("y" of bracket + .1* "y" of bracket). But given that the plot can dynamically change (i.e., the plot is connected to a function), + .1* "y" of bracket in any plot gives a different position for the text that doesn't guarantee the distance between he text and the bracket be always maintained.
Here is a piece of R code:
if(!require(library(pBrackets))){install.packages('pBrackets') }
library(pBrackets)
plot(1:10, ty = 'n')
brack <- brackets(x1 = 4, y1 = 6, x2 = 8, y2 = 6, h = 1, ticks = .5, curvature = .5,
type=1, col = "blue",
lwd = 2, xpd = T)
text(x = 6, y = 7.2, "Equivalent to ZERO", font = 2) ## How to determine "x" and "y"
# such that the "text" always
# appears above the bracket
# even if the plot changes. This helps making functions.

plot(1:10, ty = 'n')
x1 = 4
y1 = 6
x2 = 8
y2 = 6
h = 1 #Or some variation of h = sqrt( (x2-x1)^2 + (y2-y1)^2 )/4
brack <- brackets(x1 = x1, y1 = y1, x2 = x2, y2 = y2, h = h, ticks = .5, curvature = .5,
type=1, col = "blue",
lwd = 2, xpd = T)
text(x = (x1+x2)/2, y = (y1+h), "Equivalent to ZERO", font = 2, pos = 3)
#pos = 3 means the text will be on top of x and y

Related

Function hdr.den(), problem with intervals of x axis

I have a problem with the function hdr.den, I can't modify the intervals of axis x, and the graphic is printed only with default values. My code is:
library(hdrcde)
dades <- data.frame(via = c("A-2", "A-2", "A-2"), pk = c(450, 450.2, 451), valor = c(3, 1, 2))
dens <- density(dades$pk, bw = 0.1)
nBreaks = 10
xaxpi <- c(trunc(min(dades$pk)), trunc(max(dades$pk)), nBreaks)
hdr <- hdr.den(round(dades$pk, 1), den = dens,
xaxp = xaxpi, cex.axis = 0.6, las = 2,
main = paste("Concentraciones relativas"))
Although I modify the variable nBreaks, the axis doesn't change:
I have also tried to completely delete the divisions of axis x, by this way:
xaxp = "n"
But it neither works.
The last I have tried is to put the axis by manual, with this function:
axis(side= 1, xaxp= xaxpi)
But then they appear overhead:
I would appreciate if someone knows how to solve it.

Place points at different places on filled.contour3 plots

I am using the filled.contour3 function in the mannner described here. My code is like this
plot.new()
par(mfrow = c(3,3))
pop_x <- 3.0
pop_y <- 6.0
for (i in 1:9){
b_x <- calc_b_x(i)
b_y <- calc_b_y(i)
x <- calc_x(i)
y <- calc_y(i)
z <- calc_z(i)
filled.contour3(x, y, z)
text(x = pop_x, y = pop_y , 'x', cex = 1.5, font = 2)
text(x = b_x, y = b_y , 'a', cex = 1.5, font = 2)
}
This successfully plots 9 graphs in 3 rows. It also puts one 'x' on each graph in the correct position. However the second text call ends up putting 9 'a's on each plot, each in right position. But I only on want one 'a' on each graph, in the correct position for that graph. How do I fix this?
It turns out it was not a problem with filled.contour3. The b_x and b_y were mistakenly vectors rather than scalars, so a single call to
text(x = b_x, y = b_y , 'a', cex = 1.5, font = 2)
produced many points.

adding all possible connections between dots in r plot

I have data-frame DOTS with following columns: DOT, X, Y. There are 10 dots.
I want to display all possible connections: (a) between dots 1,2,3,4,5; (b) 5,6,7; and (c) between 7,8,9,10?
# what I tried so far
plot(DOTS$X, DOTS$Y, main= "DOTS", xlab= "X", ylab= "Y",
col= "blue", pch = 19, cex = 1, lty = "solid", lwd = 2)
text(DOTS$X, DOTS$Y, labels=DOTS$Dot, cex= 0.7, pos = 3)
lines(DOTS$X,DOTS$Y)
# the last line displays connection from 1 to 2 to 3 etc only
Thank you in advance for your suggestions.
I make a dataset first :
x <- runif(10, 0, 10)
y <- runif(10, 0, 10)
df <- data.frame(dot = LETTERS[1:10], x = x, y = y)
I think it's flexible to create a custom function and use combn() to generate all possible combinations of two dots. And then connect them with segments() respectively. In the custom function below, you can put any dots set and arguments e.g. col, lwd... etc.
plot(df$x, df$y)
text(df$x, df$y, labels = df$dot, pos = 3)
line.fun <- function(index, ...){
comb <- combn(index, 2)
start <- comb[1, ] # starting points
end <- comb[2, ] # end points
segments(df$x[start], df$y[start], df$x[end], df$y[end], ...)
}
line.fun(1:5, col = 2)
line.fun(5:7, col = 3)
line.fun(7:10, col = 4)

title position in legend in R plot

I use the following code to draw a plot.
x = seq(-20,20,by=0.2);
c = .2;
y1 = exp(c*x);
c = .5;
y2 = exp(c*x);
c = 1;
y3 = exp(c*x);
par(mgp = c(2,.5,0)); # to adjust dist of x/y label to plot, x/y axes to plot
plot(x,
y1,
type="l",
xlab=expression(x-theta),
ylab=expression(L(x,theta)),
main="function");
lines(x,y2,col="blue");
lines(x,y3,col="green");
legend(x=-20,
y=40,
title=expression(L(x, theta)==e^{c(x-theta)}),
legend=expression("c=.2", "c=.5", "c=1"),
lty=c(1, 1, 1),
lwd=c(2.5, 2.5,2.5),
col=c("black","blue","green"));
I find that the brackets of $(x-\theta)$ in the legend exceed the box. Is there any way to move that expression down? I tried replacing the original legend function by
legend(x=-20,y=40,title.adj=c(0,.5), title=expression(L(x,theta)==e^{c(x-theta)}), legend=expression("c=.2","c=.5","c=1"), lty=c(1,1,1), lwd=c(2.5,2.5,2.5), col=c("black","blue","green"));
However, the expression appeared twice in the legend box.
Thanks!
I think it looks better without a box ( legend( ... ,bty='n') ) but if you really want a box, here's how you do it:
lgnd = legend(x=-20,
y=40,
title=expression(L(x, theta)==e^{c(x-theta)}),
legend=expression("c=.2", "c=.5", "c=1"),
lty=c(1, 1, 1),
lwd=c(2.5, 2.5,2.5),
col=c("black","blue","green"),
# no box
bty='n');
# plot your own box using the lgnd$rect as your starting point
params = lgnd$rect
rect(xleft = params[['left']],
ybottom = params[['top']] - params[['h']],
xright = params[['left']] + params[['w']],
ytop = params[['top']] + 1)

Complete missing lines using rgl grid3d

Does anyone know of a way to 1) complete the missing gridlines in the grid3d call for y, and 2) draw horizontal gridlines to close the top of the grids constructed by the grid3d calls for x and y? I've played around with various combinations of pretty calls within grid3d to no avail and am wondering if this is an rgl quirk or a misspecification on my part. Additionally, I'd like to extend the vertical axis numbering to wherever the closed grids end up.
library(rgl)
cpts <- seq(0, 2, length = 40)
spts <- seq(0, 1, length = 20)
grid <- expand.grid(s=spts, c=cpts)
UFn <- function(s,c){c^(0.5) - exp(s) + 1}
U <- UFn(grid$s, grid$c)
open3d()
rgl.surface(x = spts, y = matrix(U,nrow = 40, ncol = 20), z = cpts,
coords = c(1,3,2), specular = "black")
axes3d("x", at = pretty(spts, n = 2), color = "black")
axes3d("y", at = pretty(cpts, n = 5), color = "black")
axes3d("z--", color = "black")
grid3d("x")
grid3d("y", at = pretty(spts, n = 2))
title3d(xlab ='s', ylab = 'c', zlab = 'U', color = "black")
rgl.snapshot("3d.png")
I would say it is a bug. You don't get any z-lines when using grid3d("y",n=2) even though it should be the same. You can work around it by using the list specification of at, setting the x element of the list, eg:
grid3d("y", at = list(x=pretty(spts, n = 2)))

Resources