Julia 1.1 Create a grid (array of points in a grid) - grid

Using Julia 1.1, I want to create a grid of points based on a vector of ranges
When using this code, it gives me a list of such points
u = [[i j ] for i in -1:0.5:1, j in -1:0.5:1]
[u...]
However, I am unable to develop a more generic approach that would create such a vector of multidimensional points when given an array of ranges
For example, develop a createGrid function that would take a Vector of n ranges as argument and output a list of all the points.
createGrid([1.:0.5:0., 1.:0.5:0., 1.:0.5:0.])
that would output:
27-element Array{Array{Float64,2},1}:
[-1.0 -1.0 -1.0]
[-0.5 -1.0 -1.0]
[0.0 -1.0 -1.0]
[-1.0 -0.5 -1.0]
[-0.5 -0.5 -1.0]
[0.0 -0.5 -1.0]
[-1.0 0.0 -1.0]
[-0.5 0.0 -1.0]
[0.0 0.0 -1.0]
[-1.0 -1.0 -0.5]
[-0.5 -1.0 -0.5]
[0.0 -1.0 -0.5]
[-1.0 -0.5 -0.5]
⋮
Thank you for any suggestion

Take a look at Iterators.product. It doesn't create the Arrays, but creates an object you can iterate over to get each new element of the grid as a Tuple (which is actually usually what you want).
julia> p = Iterators.product(-1.:0.5:0., -1.:0.5:0., -1.:0.5:0.);
julia> println.(p);
(-1.0, -1.0, -1.0)
(-0.5, -1.0, -1.0)
(0.0, -1.0, -1.0)
(-1.0, -0.5, -1.0)
(-0.5, -0.5, -1.0)
(0.0, -0.5, -1.0)
(-1.0, 0.0, -1.0)
⋮

I would use:
using GeometryTypes
grid(ranges::NTuple{N, <: AbstractRange}) where N = Point.(Iterators.product(ranges...))
p = grid((-1.:0.5:0.0, -1.:0.5:0.0))
By using an NTuple instead of a Vector of ranges, this methods becomes type stable (the return type gets inferred as e.g Vector{Point{2, Float64}}).
Also, using Points is more efficient than Array{Array{Float64,1},1}, has C-compatible layout and has all the operations defined which you need for points...
As a bonus, it directly plots in Makie / Plots as points :)

Just to add to the excellent answer above, if you do want a vector-of-vectors you can collect each of the tuples into a vector, and then call vec to flatten this array-of-vectors into a vector-of-vectors
julia> p = Iterators.product(-1.0:0.5:0.0, -1.0:0.5:0.0, -1.0:0.5:0.0);
julia> collect.(p)
3×3×3 Array{Array{Float64,1},3}:
[:, :, 1] =
[-1.0, -1.0, -1.0] [-1.0, -0.5, -1.0] [-1.0, 0.0, -1.0]
[-0.5, -1.0, -1.0] [-0.5, -0.5, -1.0] [-0.5, 0.0, -1.0]
[0.0, -1.0, -1.0] [0.0, -0.5, -1.0] [0.0, 0.0, -1.0]
[:, :, 2] =
[-1.0, -1.0, -0.5] [-1.0, -0.5, -0.5] [-1.0, 0.0, -0.5]
[-0.5, -1.0, -0.5] [-0.5, -0.5, -0.5] [-0.5, 0.0, -0.5]
[0.0, -1.0, -0.5] [0.0, -0.5, -0.5] [0.0, 0.0, -0.5]
[:, :, 3] =
[-1.0, -1.0, 0.0] [-1.0, -0.5, 0.0] [-1.0, 0.0, 0.0]
[-0.5, -1.0, 0.0] [-0.5, -0.5, 0.0] [-0.5, 0.0, 0.0]
[0.0, -1.0, 0.0] [0.0, -0.5, 0.0] [0.0, 0.0, 0.0]
julia> vec(collect.(p))
27-element Array{Array{Float64,1},1}:
[-1.0, -1.0, -1.0]
[-0.5, -1.0, -1.0]
[0.0, -1.0, -1.0]
[-1.0, -0.5, -1.0]
[-0.5, -0.5, -1.0]
[0.0, -0.5, -1.0]
[-1.0, 0.0, -1.0]
⋮

Related

Orthogonal Linear Regression (total least squares) fit, get RMSE and R-squared in R

I am trying to fit a model that linearly relates two variables using R. I need to fit a Orthogonal Linear Regression (total least squares). So I'm trying to use the odregress() function of the pracma package which performs an Orthogonal Linear Regression via PCA.
Here an example data:
x <- c(1.0, 0.6, 1.2, 1.4, 0.2, 0.7, 1.0, 1.1, 0.8, 0.5, 0.6, 0.8, 1.1, 1.3, 0.9)
y <- c(0.5, 0.3, 0.7, 1.0, 0.2, 0.7, 0.7, 0.9, 1.2, 1.1, 0.8, 0.7, 0.6, 0.5, 0.8)
I'm able to fit the model and get the coefficient using:
odr <- odregress(y, x)
c <- odr$coeff
So, the model is defined by the following equation:
print(c)
[1] 0.65145762 -0.03328271
Y = 0.65145762*X - 0.03328271
Now I need to plot the line fit, compute the RMSE and the R-squared. How can I do that?
plot(x, y)
Here are two functions to compute the MSE and RMSE.
library(pracma)
x <- c(1.0, 0.6, 1.2, 1.4, 0.2, 0.7, 1.0, 1.1, 0.8, 0.5, 0.6, 0.8, 1.1, 1.3, 0.9)
y <- c(0.5, 0.3, 0.7, 1.0, 0.2, 0.7, 0.7, 0.9, 1.2, 1.1, 0.8, 0.7, 0.6, 0.5, 0.8)
odr <- odregress(y, x)
mse_odreg <- function(object) mean(object$resid^2)
rmse_odreg <- function(object) sqrt(mse_odreg(object))
rmse_odreg(odr)
#> [1] 0.5307982
Created on 2023-01-10 with reprex v2.0.2
Edit
The R^2 can be computed with the following function. Note that odr$ssq is not the sum of the squared residuals, odr$resid, it is the sum of the squared errors, odr$err.
r_squared_odreg <- function(object, y) {
denom <- sum((y - mean(y))^2)
1 - object$ssq/denom
}
r_squared_odreg(odr, y)
#> [1] 0.1494818
Created on 2023-01-10 with reprex v2.0.2
Here is another alternative to solve an Orthogonal Linear Regression (total least squares) via PCA according to what is explained in this post. It actually does the same as pracma::odregress.
x <- c(1.0, 0.6, 1.2, 1.4, 0.2, 0.7, 1.0, 1.1, 0.8, 0.5, 0.6, 0.8, 1.1, 1.3, 0.9)
y <- c(0.5, 0.3, 0.7, 1.0, 0.2, 0.7, 0.7, 0.9, 1.2, 1.1, 0.8, 0.7, 0.6, 0.5, 0.8)
In this case we perform a Principal Component Analysis using the prcomp() function.
v <- prcomp(cbind(x,y))$rotation
Then we calculate the slope (m) from the firs principal component and the intercept (n):
# Y = mX + n
m <- v[2,1]/v[1,1]
n <- mean(y) - (m*mean(x))
Our model is defined by: f <- function(x){(m*x) + n}
We can plot it using:
plot(x, y)
abline(n, m, col="blue")
Finally we plot the Total Least Squares fit versus the Ordinary Least Squares fit.
plot(x, y)
abline(n, m, col="blue")
abline(lm(y~x), col="red")
legend("topleft", legend=c("TLS", "OLS"), col=c("blue", "red"), lty=1, bty="n")
As you can see we obtain the same results as in pracma::odregress:
odr <- odregress(y, x)
print(odr$coeff)
print(paste(round(m, digits=7), round(n, digits=7)))
[1] 0.5199081 0.2558142
[1] 0.5199081 0.2558142

Is it possible to manage number format in guide_colorsteps?

I want to ask if it is possible to fix labels generated by the guide_colorsteps function in the same format with breaks used in the geom_contour_filled function used for plotting?
Here is my example:
ggplot(faithfuld, aes(y=eruptions, x=waiting, z=100*density)) +
geom_contour_filled(breaks = c(-Inf, -2.0, -1.5, -1.0, -0.05, -0.005, 0, 0.005, 0.05, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0, 7.0, 9.0, 11.0, Inf)) +
theme(plot.title = element_text(size = 10,hjust = 0.5)) +
scale_fill_manual(values = heat.colors(18),drop=FALSE) +
guides(fill = guide_colorsteps(barheight = unit(par("pin")[2], "in")))
which gives an output like this:
enter image description here
As you can see in the legend, there are added zeros to the numbers used in breaks (0 -> 0.000, 1.0 -> 1.000 etc.). I would like to have the numbers in the legend in the same format as I wrote them in the breaks.
Thanks a lot for any suggestions.

Algorithm to generate RYB color wheel?

I am attempting to generate a color wheel, but in RYB space. I have successfully implemented this in RGB. I start off with Red (255, 0, 0) and convert it to HSL, increment the hue value, then convert back to display on screen. The details are described here: https://serennu.com/colour/rgbtohsl.php
However, my attempts at doing so with RYB have not worked so far.
From what I have read, you get a value in RGB, such as Red (255, 0, 0). Then you ASSUME that it's RYB and use the code below to convert that "RYB" value to RGB. Then, what I have done is gotten that value, converted it to HSL, incremented the Hue, and then displayed it on the screen as before.
def _cubic(t, a, b):
weight = t * t * (3 - 2*t)
return a + weight * (b - a)
def ryb_to_rgb(r, y, b): # Assumption: r, y, b in [0, 1]
# red
x0, x1 = _cubic(b, 1.0, 0.163), _cubic(b, 1.0, 0.0)
x2, x3 = _cubic(b, 1.0, 0.5), _cubic(b, 1.0, 0.2)
y0, y1 = _cubic(y, x0, x1), _cubic(y, x2, x3)
red = _cubic(r, y0, y1)
# green
x0, x1 = _cubic(b, 1.0, 0.373), _cubic(b, 1.0, 0.66)
x2, x3 = _cubic(b, 0., 0.), _cubic(b, 0.5, 0.094)
y0, y1 = _cubic(y, x0, x1), _cubic(y, x2, x3)
green = _cubic(r, y0, y1)
# blue
x0, x1 = _cubic(b, 1.0, 0.6), _cubic(b, 0.0, 0.2)
x2, x3 = _cubic(b, 0.0, 0.5), _cubic(b, 0.0, 0.0)
y0, y1 = _cubic(y, x0, x1), _cubic(y, x2, x3)
blue = _cubic(r, y0, y1)
return (red, green, blue)
I expect to get the RYB color wheel as described here: Calculating the analogous color with python
I have followed the instructions on this post, and still am getting the wrong colors. I have tested this algorithm on a linear path (not a circle) to get http://prntscr.com/o3gcjr
This looks similar to the color wheel on that post I linked to above. However, when starting the wheel from a different color, I get this http://prntscr.com/o3gp76
And in my opinion, that doesn't seem correct.

Using float positions on the x axis of an R plot with integer scaled x axis

I have a plot with a discrete x axis from 0.0 to 1.0 in 0.1 steps that I use to represent the continuous range from 0 to 1.
And I have data in ay, by, cy and so on and x positions for these in ax, bx, cx, that have finer granularity and different values than the x axis currently has.
All vectors have the same length.
Here an example showing the ay values on the wrong x positions.
x <- seq(0, 1, 0.1)
ax <- c(0.08, 0.13, 0.172, 0.2224, 0.357, 0.42, 0.551, 0.76, 0.79, 0.81, 0.92)
ay <- c(113.4, 111, 162.2, 35, 5, 4, 64, 74, 91, 93, 91)
plot(x, ay, type="b")
Is it possible without ggplot2 to realign the x positions of the y values according to ax, bx, cx? (ax != bx != cx)
Why not use plot(ax, ay), and then use axis() to specify the ticks from 0.0 to 1.0?
plot(ax, ay, type="b")
axis(1, at = seq(0, 1, 0.1))
Then plot bx and by together, cx and cy, etc.

how to customize y-axis step size in R

I would like to plot a scatterplot with y-axis is customized to step size of 0.2, within range of 0 - 2.6, and x-axis can be auto-defined. I tried the below, but it doesnt work. May I know how should I set the param correctly?
# Read data
pt.n <- read.table("p0_n300m20r1c1_regression.txt", header=T)
# auto-scale
# plot(pt.n$maee~pt.n$idx, main="P2PSim Seq#1,300n,20%,1r,Corrective", ylab="MAEE", xlab="Seq #")
# customize
ylabel <- c(0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6)
y_range <- range(0, ylabel)
plot(pt.n$maee~pt.n$idx, main="P2PSim Seq#3,300n,20%,1r,Corrective", ylab="MAEE", xlab="Seq #", ylim=y_range, axes=FALSE, ann=FALSE)
axis(1, at=0:6, lab=c(0,50,100,150,200,250,300))
axis(2, las=1, at=0.2*0:y_range[1])
box()
If something is not working check each bit of the thing that isn't doing what you want to make sure you are supplying the correct data and haven't made a booboo. If we run the bits of your code that are associated with the axis
ylabel <- c(0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6)
y_range <- range(0, ylabel)
0.2*0:y_range[1]
You would immediately see the problem:
R> 0.2*0:y_range[1]
[1] 0
where you are basically telling R to draw a tick at 0. Even if you chose the correct element of y_range (the maximum is in the second element) you still wouldn't get the right answer:
R> 0.2*0:y_range[2]
[1] 0.0 0.2 0.4
R> 0:y_range[2]
[1] 0 1 2
and that is because of the way the : operator works. A call of x:y is essentially a call to seq(from = x, to = y, by = 1) and because 2.6+1 is greater than 2.6 (the to argument) R creates the sequence 0, 1, 2.
If you want to draw ticks and label at 0 - 2.6 incrementing by 0.2 then use:
ylabel <- seq(0, 2.6, by = 0.2)
axis(2, at = ylabel)
where ylabel now contains:
R> ylabel
[1] 0.0 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0 2.2 2.4 2.6
To illustrate:
dat <- data.frame(y = runif(20, min = 0, max = 3),
x = rnorm(20))
plot(y ~ x, data = dat, axes = FALSE)
ylabel <- seq(0, 2.6, by = 0.2)
axis(1)
axis(2, at = ylabel, las = 1)
box()
which produces

Resources