Is there a way to specify a 'center' parameter using segments() without specifying individual x0/1 and y0/1 coordinates? Obviously align = 'center' does not work for this as the segments() function is base r code.
#Here is short excerpt from my code:
plot.new()
height1 = 0.9
height3 = 0.7
height5 = 0.5
height4 = 0.3
height2 = 0.1
segments(0, height1, species1_length/largestLength, height1,
lwd=3)
segments(0, height2, species2_length/largestLength, height2,
lwd=3)
segments(0, height3, species3_length/largestLength, height3,
lwd=3)
segments(0, height4, species4_length/largestLength, height4,
lwd=3)
segments(0, height5, species5_length/largestLength, height4,
lwd=3)
I ended up just doing it manually like so:
segments(0.143, height1, ((species1_length / largestLength) * 2) + 0.143,
height1, lwd = 3)
segments(0.16, height2, ((species2_length / largestLength) * 2) + 0.16,
height2, lwd = 3)
segments(0.258, height3, ((species3_length / largestLength) * 2) + 0.258,
height3, lwd = 3)
segments(0.083, height4, ((species4_length / largestLength) / 1.2) +
0.083,
height4, lwd = 3)
segments(0.155, height5, ((species5_length / largestLength) *
2) + 0.155,
height5, lwd = 3)
I just picked an amount to shift the x0 parameter (segments(x0,y0,x1,y1)) and corrected the x1 value by that amount. The length of the line is still the same but my initial value and the proportional shift stay equidistant
I would write a function to do this. For example, I think this should work:
centered_segments <- function(length, height, largest = max(length), ...) {
padding <- (largest - length)/2
segments( padding, height, padding + length, height, ... )
}
You would call it like this:
centered_segments( species_lengths, heights, lwd = 3 )
where species_lengths is a vector containing all of the lengths and heights contains all of the heights, or one at a time like
centered_segments( species1_length, height1, largest_length, lwd = 3 )
etc.
Related
https://bootstrappers.umassmed.edu/bootstrappers-courses/pastCourses/rCourse_2014-09/resources/helpfulGuides/Rfigurelayout.pdf
The above doc shows plot region, figure region, and device region.
Suppose these regions are mentally mapped to coordinates from 0 (the bottom or the left) to 1 (the top or the right). How to put text in this definition of coordinates on these three regions in basic R, respectively?
I think what you are asking is how to place text anywhere in the plotting window, using proportional device co-ordinates. This is actually how text works in the grid graphic system:
library(grid)
grid.newpage()
grid.draw(rectGrob(gp = gpar(lwd = 2)))
grid.draw(textGrob("(0.1, 0.1)", 0.1, 0.1, gp = gpar(cex = 2, col = "red2")))
grid.draw(textGrob("(0.5, 0.5)", 0.5, 0.5, gp = gpar(cex = 2, col = "blue")))
grid.draw(textGrob("(0.9, 0.9)", 0.9, 0.9, gp = gpar(cex = 2, col = "green2")))
However, if you want to do the same thing in base R graphics, I think you would need to write a wrapper around text that queries the graphics device and converts your device space co:ordinates to user co-ordinates, then draws the text with clipping off.
Here is such a function (called dtext to denote "device text")
dtext <- function(x = 0.5, y = 0.5, label, ...) {
margins <- par("omi") + par("mai")
plotsize <- par("pin")
devsize <- dev.size()
usr_space <- par("usr")
usr_y <- devsize[2] / plotsize[2] * (diff(usr_space[3:4]))
y_min <- usr_space[3] - usr_y * margins[1]/devsize[2]
usr_x <- devsize[1] / plotsize[1] * (diff(usr_space[1:2]))
x_min <- usr_space[1] - usr_x * margins[2]/devsize[1]
text(x = x * usr_x + x_min,
y = y * usr_y + y_min,
label = label,
xpd = NA,
...)
}
This allows:
plot(1:10, 1:10)
dtext(x = 0.1, y = 0.1, label = "(0.1, 0.1)", cex = 2, col = "red2")
dtext(x = 0.5, y = 0.5, label = "(0.5, 0.5)", cex = 2, col = "blue2")
dtext(x = 0.9, y = 0.9, label = "(0.9, 0.9)", cex = 2, col = "green2")
This seems like a pretty useful function, and I'm surprised it doesn't exist already, so thanks for the OP.
Created on 2022-04-02 by the reprex package (v2.0.1)
I am trying to compare two measurement methods with Bland-Altman plot, which is basically this:
method.1 <- rnorm(20)
method.2 <- rnorm(20)
plot((method.1 + method.2)/2, method.1 - method.2)
I've found a package that I like:
devtools::install_github("deepankardatta/blandr")
library(blandr)
blandr.draw(method.1, method.2, plotter = "rplot")
Which gives me the following result:
Bland-Altman plot with blandr package
The upper band is Mean + 1.96 SD (+/- 95% CI)
The lower band is Mean - 1.96 SD (+/- 95% CI)
The middle band is Mean +/- 95% CI
I like the way it is, although I wish I could change the bands colours, line types, points shape or include the legend.
I wish I could overwrite the blandr.draw() function or just create my own plot ( same as blandr.draw() ) using base R so I can customize it the way I want. I failed to contact the package author...
Additionally - ggplot version of similar plot ( blandr.draw(method.1, method.2) ) will be appreciated.
So here is my self-made Bland-Altman plot - maybe it will be useful for others.
Sample Bland-Altman plot
All calculations (Lines of agreement and 95% Confidence Intervals) based on Bland and Altman paper from 1999: Measuring agreement in method comparision studies.
I still don't know how to shade bands between Confidence Intervals - probably with rect() function.
# Sample data:
method.1 <- rnorm(100)
method.2 <- rnorm(100)
df <- data.frame(
X = (method.1 + method.2)/2,
Y = (method.1 - method.2)
)
# Number of measurements to calculate degrees of freedom for t-distribution:
n = length(df$Y)
t = qt(0.975, df = n - 1) # t-distribution
mean <- mean(df$Y)
LoA <- 1.96*sd(df$Y) # Lines of Agreement
# 95% Confidence Intervals:
LoA_CI <- t * sqrt( (1/n + 3.8416/(2*(n - 1))) ) * sd(df$Y)
mean_CI <- t * sd(df$Y)/sqrt(n)
# To calculate position of partition lines:
LoA_up_plus <- mean + LoA + LoA_CI
LoA_up <- mean + LoA
LoA_up_minus <- mean + LoA - LoA_CI
mean_plus <- mean + mean_CI
mean_minus <- mean - mean_CI
LoA_down_plus <- mean - LoA + LoA_CI
LoA_down <- mean - LoA
LoA_down_minus <- mean - LoA - LoA_CI
# Save PNG file:
png(filename = "BA_norm.png",
width = 3000, height = 2100, units = "px", res = 300)
# Plot:
plot(Y ~ X, df,
# When I have a lot of data my points are overlapping each other
# that's why I make them semi-transparent with 'alpha':
col = rgb(0, 0, 0, alpha = 0.5), pch = 16, cex = 0.75,
main = "Bland-Altman plot for Mathod 1 and Method 2",
xlab = "Mean of results",
ylab = "Method 1 - Method 2 difference"
)
# Background colour for your plot, if you don't want it
# just skip following four lines of code:
rect(par("usr")[1], par("usr")[3], par("usr")[2], par("usr")[4],
col = "#c2f0f0") #here you can put desired background colour hex
points(Y ~ X, df,
col = rgb(0, 0, 0, alpha = 0.5), pch = 16, cex = 0.75)
# Adding lines:
abline(h = 0, lwd = 0.7) # solid line for Y = 0
# Display rounded values of partition lines positions:
text(x = 1.5, y = LoA_up_plus, # x and y position of text
paste(round(LoA_up, 2), "\u00B1", round(LoA_CI, 2)), pos = 1)
abline(h = LoA_up_plus, col = "#68cbf8", lty = "dotted")
abline(h = LoA_up, col = "blue", lty = "dashed")
abline(h = LoA_up_minus, col = "#68cbf8", lty = "dotted")
text(x = 1.5, y = mean_plus,
paste(round(mean, 2), "\u00B1", round(mean_CI, 2)), pos = 3)
abline(h = mean_plus, col = "#ff9e99", lty = "dotted")
abline(h = mean, col = "red", lty = "longdash")
abline(h = mean_minus, col = "#ff9e99", lty = "dotted")
text(x = 1.5, y = LoA_down_plus,
paste(round(LoA_down, 2), "\u00B1", round(LoA_CI, 2)), pos = 3)
abline(h = LoA_down_plus, col = "#68cbf8", lty = "dotted")
abline(h = LoA_down, col = "blue", lty = "dashed")
abline(h = LoA_down_minus, col = "#68cbf8", lty = "dotted")
# Close saving PNG file function:
dev.off()
I guess it is possible to easily condense all those abline() functions.
I'm currently working on SOM vizualisations.
This is a SOM map with codes plots generated by using kohonen package
Shortly, each circle is a neuron and inside each neuron we plot all the variable in a spectra shape.
This plot is obtain by som_obj$codes[nameoftheneuron] (som_obj is the return value of som() function)
here i have written basic function derived from https://github.com/geoss/som_visualization_r
plotCluster <- function(som_obj, cutree.obj , col_palette){
if (som_obj$grid$topo != "hexagonal"){
stop("function assumes hexgonal SOM")
}
Hexagon <- function (x, y, unitcell = 1, col = "grey", border=NA) {
polygon(c(x, x, x + unitcell/2, x + unitcell, x + unitcell,
x + unitcell/2), c(y + unitcell * 0.125, y + unitcell *
0.875, y + unitcell * 1.125, y + unitcell * 0.875,
y + unitcell * 0.125, y - unitcell * 0.125),
col = col, border=border)
}
plot(0, 0, type = "n", axes = FALSE, xlim=c(0, som_obj$grid$xdim),
ylim=c(0, som_obj$grid$ydim), xlab="", ylab= "", asp=1, main= "Clusters")
if(!is.null(col_palette)){
ColorCode = col_palette[cutree.obj]
}
else{
ColorCode <- as.factor(cutree.obj)
}
offset <- 0.5 #offset for the hexagons when moving up a row
ind <- 1
for (row in 1:som_obj$grid$ydim) {
for (column in 0:(som_obj$grid$xdim - 1)) {
Hexagon(column + offset, row - 1, col = ColorCode[ind])
ind <- ind +1}
offset <- ifelse(offset, 0, 0.5)
}
}
I only want to know how to add each plot in the tiles on my own plot.
I have 0 idea how to perform that. I have literally no clue for doing that.
I tried to get the code of the plot function from plot.kohonen but I get the truncated code only from getAnywhere(plot.kohonen)
This problem seems to be complex but I just need hints with the following question:
1 - In the plot systems imagined in the code below, how to plot something (plot or text) in each tiles?
I'm trying to do a task, where I have to compare the histogram of a sample with poisson distribution of size 100, with the expected frequencies that they should have, so I did this.
prob0 = dpois(0, 2.5)
prob1 = dpois(1, 2.5)
prob2 = dpois(2, 2.5)
prob3 = dpois(3, 2.5)
prob4 = dpois(4, 2.5)
prob5 = dpois(5, 2.5)
prob6 = dpois(6, 2.5)
prob7 = dpois(7, 2.5)
prob8 = dpois(8, 2.5)
prob9 = dpois(9, 2.5)
n100 = rpois(100, 2.5)
hist(n100)
y <- c(rep(prob0 * 100), rep(prob1 * 100), rep(prob2 * 100), rep(prob3 * 100), rep(prob4 * 100), rep(prob5 * 100), rep(prob6 * 100), rep(prob7 * 100), rep(prob8 * 100), rep(prob9 * 100))
lines(y, col="blue")
Resulting in:
The problem I have is that by using the command line with a vector as an argument, it begins to plot the line from position 1, I guess it's because R indexes start from number 1, but I need it to begins to plot from the position 0, what I can do?
To fix it I thought I could make the vector's index start from 0, but I don't know how.
You can just add the x to the plot
lines(1 : length(y) - 1, y, col="blue")
I am trying to plot a (filled) contour map with aspect ratio = 1, but I fail to get the right shape of the plot window/ am left with areas in the plot window that are white because the plot window (or the box) always remains a square. Please see the example below
x <- 10*1:nrow(volcano)
y <- 10*1:ncol(volcano)
filled.contour (x, y, volcano, asp = 1)
results in a plot that looks like this:
how do I get rid of the white areas in the plot box/window while preserving the aspect ratio? I assume I need to set the size of the plot window somewhere, but can't find out how; it seems that graphical parameter settings (using par) are overwritten by filled.contour (or by setting asp = 1)
I experienced a the same problem for a project of mine. I worked out a solution by adjusting the filled.contour()-function in a way that the box is only drawn around the area, where values are observed. Also the legend is fitted to the adjusted box. By applying the customized function filled.contourNew(), I get the following plot:
Adjusted Filled Contour Plot
filled.contourNew <- function (x = seq(0, 1, length.out = nrow(z)),
y = seq(0, 1, length.out = ncol(z)), z, xlim = range(x, finite = TRUE),
ylim = range(y, finite = TRUE), zlim = range(z, finite = TRUE),
levels = pretty(zlim, nlevels), nlevels = 20,
color.palette = cm.colors, col = color.palette(length(levels) - 1),
plot.title, plot.axes, key.title, key.axes, asp = NA, xaxs = "i",
yaxs = "i", las = 1, axes = TRUE, frame.plot = axes, ...)
{
if (missing(z)) {
if (!missing(x)) {
if (is.list(x)) {
z <- x$z
y <- x$y
x <- x$x
}
else {
z <- x
x <- seq.int(0, 1, length.out = nrow(z))
}
}
else stop("no 'z' matrix specified")
}
else if (is.list(x)) {
y <- x$y
x <- x$x
}
if (any(diff(x) <= 0) || any(diff(y) <= 0))
stop("increasing 'x' and 'y' values expected")
mar.orig <- (par.orig <- par(c("mar", "las", "mfrow")))$mar
on.exit(par(par.orig))
w <- (3 + mar.orig[2L]) * par("csi") * 2.54
layout(matrix(c(2, 1), ncol = 2L), widths = c(1, lcm(w)))
par(las = las)
mar <- mar.orig
mar[4L] <- mar[2L]
mar[2L] <- 1
par(mar = mar)
pin1 <- par("pin")
a = (pin1[1] + par("mai")[2] + par("mai")[4])
b = (pin1[2] + par("mai")[1] + par("mai")[3])
ratio <- abs(diff(ylim)) / abs(diff(xlim))
ratioXY <- (a / b) * asp
if (abs(diff(xlim)) / abs(diff(ylim)) >= ratioXY){
par(plt = c(0.15, 0.5, 0.525 - ratio * ratioXY / 2 * 0.75,
0.525 + ratio * ratioXY / 2 * 0.75))
}
if (abs(diff(xlim)) / abs(diff(ylim)) < ratioXY){
par(plt = c(0.15, 0.5, 0.15, 0.9))
}
plot.new()
plot.window(xlim = c(0, 1), ylim = range(levels), xaxs = "i",
yaxs = "i")
rect(0, levels[-length(levels)], 1, levels[-1L], col = col)
if (missing(key.axes)) {
if (axes)
axis(4)
}
else key.axes
box()
if (!missing(key.title))
key.title
mar <- mar.orig
mar[4L] <- 1
par(mar = mar)
#browser()
a = (pin1[1] + par("mai")[2] + par("mai")[4])
b = (pin1[2] + par("mai")[1] + par("mai")[3])
ratio <- abs(diff(ylim)) / abs(diff(xlim))
ratioXY <- (a / b) * asp
if (abs(diff(xlim)) / abs(diff(ylim)) >= ratioXY){
par(plt = c(0.15, 0.9, 0.525 - ratio * ratioXY / 2 * 0.75,
0.525 + ratio * ratioXY / 2 * 0.75))
}
if (abs(diff(xlim)) / abs(diff(ylim)) < ratioXY){
par(plt = c(0.525 - 1 / ratioXY / 2 * 0.75 / ratio,
0.525 + 1 / ratioXY / 2 * 0.75 / ratio, 0.15, 0.9))
}
plot.new()
plot.window(xlim, ylim, "", xaxs = xaxs, yaxs = yaxs, asp = asp)
.filled.contour(x, y, z, levels, col)
if (missing(plot.axes)) {
if (axes) {
title(main = "", xlab = "", ylab = "")
Axis(x, side = 1)
Axis(y, side = 2)
}
}
else plot.axes
if (frame.plot)
box()
if (missing(plot.title))
title(...)
else plot.title
invisible()
}
Try this
x <- 10*1:nrow(volcano)
y <- 10*1:ncol(volcano)
filled.contour(x, y, volcano,asp=1, frame.plot=F,
plot.axes = { axis(1, pretty(x,min=0), line=-4)
axis(2, seq(0, 600, by = 100)) })