I'm no real mathematician (OK, I'm a statistician, but here it doesn't help ...), and this is my first question here, so excuse me if my question doesn't make much mathematical sense.
I need to get my brains around a transformation which would enable me to fit a segment of an n-dimensional data cloud into the first "quadrant" of an n-space. More specifically, I have a portion of data bordered by the data centroid and n data points, each with maximum in one of the dimensions. I want to "stretch" the "cone" to get the extreme points in line with the positive axes to which they have the max value. That, I imagine, would make this transformation alike to opening a fan.
I'm looking for a sort of transformation on a sphere, so the points would "move" in arcs. This would mean (and that is what I'm after), that the order of points in one dimension is not necessarily preserved.
At first, it looked like affine and projective transformations were not enough, but since the only thing that is changing are the angles, I found out that when the coordinates are translated into spheric coordinates, the transform is a matter of calculating the ratios of the angles (is this an affine transform?).
Here is a small example of the 2D transform in R:
library(SphericalCubature)
library(plotrix)
fan_transform <- function(df, titl = "") {
mx <- as.matrix(df)
maks <- apply(mx, 2, which.max)
pol_df <- rect2polar(t(mx))
pol_df$phi <- ifelse(pol_df$phi > pi, pol_df$phi - 2*pi, pol_df$phi)
first_phi <- as.vector(pol_df$phi)
max_in_d <- pol_df$phi[maks[1]]
# pol_df$phi <- pol_df$phi * (pol_df$phi / max_in_d - 1)
pol_df$phi <- ifelse(pol_df$phi < pi/2, pol_df$phi - max_in_d * (pi/2 - pol_df$phi) / (pi/2 - abs(max_in_d)), pol_df$phi)
second_phi <- as.vector(pol_df$phi)
tr_df <- t(polar2rect(pol_df$r, pol_df$phi))
min_x <- min(min(tr_df[, 1], min(df[1])))
min_y <- min(min(tr_df[, 2], min(df[2])))
max_x <- max(max(tr_df[, 1], max(df[1])))
max_y <- max(max(tr_df[, 2], max(df[2])))
plot(df, main = titl, asp = 1, xlim = c(min_x, max_x), ylim = c(min_y, max_y))
points(tr_df, col = 2)
for (i in 1:nrow(tr_df)) {
lines(rbind(c(0, 0), tr_df[i, ]), lty = 3, col = 2)
}
for (i in 1:nrow(mx)) {
lines(rbind(c(0, 0), mx[i, ]), lty = 3)
}
points(mx[maks[1], 1], mx[maks[1], 2], pch = 19)
points(tr_df[maks[1], 1], tr_df[maks[1], 2], col = 2, pch = 19)
draw.arc(rep(0, length(first_phi)), rep(0, length(first_phi)), radius = pol_df$r, angle1 = first_phi, angle2 = second_phi, lty = 2)
legend(0.05, 0.9, legend = c("reference point", "reference transform","original points", "transformed points"), pch = c(19, 19, 1, 1), col = c(1, 2, 1, 2))
}
df <- data.frame("x1" = c(0.0, 0.21, 0.15, 0.88, 0.94, 0.83, 0.61),
"x2" = c(0.4, 0.52, 0.70, 0.87, 0.38, 0.41, 0.39))
fan_transform(df, "Fan transform")
This is a positive segment of the data, so the centroid is already at origin and the non-positive points are eliminated. The point 5 is the point with maximum value at the first dimension and is therefore the reference point.
The resulting figure:
The referent point in the diagram is aligned to the x-axis and other points are transformed proportionally to their angle and distance from the centroid (origin), literally like opening a fan. The point at x = 0 is unaffected. I hope this helps.
My questions are:
- what kind of transform can I use to achieve this effect, and
- how would a generalization of this transform to higher dimensions look like.