The “woylier” package provides alternative method for generating a tour path by interpolating between d-D frames in p-D space rather than d-D planes. A tour path is a sequence of projection and we use interpolation method to produce the path. The package uses geodesic interpolation between planes. Geodesic interpolation path is the locally shortest path between planes with no within-plane spin. As a result of this method, the rendered target plane could be the rotated version of the target plane we wanted. This is not a problem when the structure we are looking can be identified without turning the axis around.
The “woylier” package implements the Givens interpolation paths method proposed by Buja et al. (2005) in R. This algorithm adapts Given’s matrix decomposition technique which allows the interpolation to be between frames rather than planes.
Installation
You can install the development version of woylier from GitHub with:
# install.packages("remotes")
remotes::install_github("numbats/woylier")
Path 1
In this example, we have 2 random 1D basis in 6D data space and the
givens_full_path()
function returns the intermediate
interpolation step projections in given number of steps. The code chunk
below demonstrates the interpolation between 2 random basis in 5
steps.
# Generate 1D example
set.seed(2022)
p <- 6
base1 <- tourr::basis_random(p, d=1)
base2 <- tourr::basis_random(p, d=1)
base1
#> [,1]
#> [1,] 0.24406482
#> [2,] -0.31814139
#> [3,] -0.24334450
#> [4,] -0.39166263
#> [5,] -0.08975114
#> [6,] -0.78647758
base2
#> [,1]
#> [1,] -0.6256883
#> [2,] 0.1641842
#> [3,] 0.4427114
#> [4,] 0.1426996
#> [5,] 0.5943406
#> [6,] -0.1093633
givens_full_path(base1, base2, nsteps = 5)
#> , , 1
#>
#> [,1]
#> [1,] 0.24406482
#> [2,] -0.31814139
#> [3,] -0.24334450
#> [4,] -0.39166263
#> [5,] -0.08975114
#> [6,] -0.78647758
#>
#> , , 2
#>
#> [,1]
#> [1,] 0.01086858
#> [2,] -0.27240617
#> [3,] -0.08264232
#> [4,] -0.35891689
#> [5,] 0.14040479
#> [6,] -0.87767429
#>
#> , , 3
#>
#> [,1]
#> [1,] -0.22389989
#> [2,] -0.18726515
#> [3,] 0.09001476
#> [4,] -0.27425086
#> [5,] 0.35025000
#> [6,] -0.84190816
#>
#> , , 4
#>
#> [,1]
#> [1,] -0.42627939
#> [2,] -0.07503468
#> [3,] 0.24965046
#> [4,] -0.14991218
#> [5,] 0.50942866
#> [6,] -0.68435306
#>
#> , , 5
#>
#> [,1]
#> [1,] -0.566994057
#> [2,] 0.048050183
#> [3,] 0.373172156
#> [4,] -0.003887462
#> [5,] 0.594914254
#> [6,] -0.427800630
#>
#> , , 6
#>
#> [,1]
#> [1,] -0.6256883
#> [2,] 0.1641842
#> [3,] 0.4427114
#> [4,] 0.1426996
#> [5,] 0.5943406
#> [6,] -0.1093633
Path 2
In this example, we have 2 random 2D basis in 6D data space and the
givens_full_path()
function returns the intermediate
interpolation step projections in given number of steps. The code chunk
below demonstrates the interpolation between 2 random basis in 5
steps.
# Generate 2D example
set.seed(2022)
p <- 6
base3 <- tourr::basis_random(p, d=2)
base4 <- tourr::basis_random(p, d=2)
base3
#> [,1] [,2]
#> [1,] 0.24406482 -0.57724655
#> [2,] -0.31814139 0.06085804
#> [3,] -0.24334450 0.38323969
#> [4,] -0.39166263 0.01182949
#> [5,] -0.08975114 0.59899558
#> [6,] -0.78647758 -0.39657839
base4
#> [,1] [,2]
#> [1,] -0.64550501 -0.17034478
#> [2,] 0.06108262 0.87051018
#> [3,] -0.03470326 0.26771612
#> [4,] -0.05281183 0.25452167
#> [5,] -0.43004248 0.27472455
#> [6,] -0.62502981 0.03560765
givens_full_path(base3, base4, nsteps = 5)
#> , , 1
#>
#> [,1] [,2]
#> [1,] 0.24406482 -0.57724655
#> [2,] -0.31814139 0.06085804
#> [3,] -0.24334450 0.38323969
#> [4,] -0.39166263 0.01182949
#> [5,] -0.08975114 0.59899558
#> [6,] -0.78647758 -0.39657839
#>
#> , , 2
#>
#> [,1] [,2]
#> [1,] 0.02498501 -0.57109655
#> [2,] -0.26080833 0.26281744
#> [3,] -0.19820064 0.40439307
#> [4,] -0.35542927 0.08342651
#> [5,] -0.14433023 0.57634009
#> [6,] -0.86308174 -0.31955295
#>
#> , , 3
#>
#> [,1] [,2]
#> [1,] -0.1909937 -0.5292778
#> [2,] -0.1874044 0.4552848
#> [3,] -0.1459678 0.4048872
#> [4,] -0.2970111 0.1523640
#> [5,] -0.2003186 0.5263904
#> [6,] -0.8824688 -0.2198760
#>
#> , , 4
#>
#> [,1] [,2]
#> [1,] -0.38527579 -0.4462372
#> [2,] -0.10411664 0.6265334
#> [3,] -0.09577045 0.3815665
#> [4,] -0.22183655 0.2092198
#> [5,] -0.26412984 0.4538619
#> [6,] -0.84414115 -0.1138933
#>
#> , , 5
#>
#> [,1] [,2]
#> [1,] -0.54115467 -0.3240743
#> [2,] -0.01855341 0.7665407
#> [3,] -0.05630484 0.3348197
#> [4,] -0.13748432 0.2454803
#> [5,] -0.34020920 0.3668276
#> [6,] -0.75431619 -0.0215393
#>
#> , , 6
#>
#> [,1] [,2]
#> [1,] -0.64550501 -0.17349072
#> [2,] 0.06108262 0.86870187
#> [3,] -0.03470326 0.26920160
#> [4,] -0.05281183 0.25552018
#> [5,] -0.43004248 0.27581107
#> [6,] -0.62502981 0.03776552
Examples
To see how to use this for examining projections of multivariate data, see Batsaikhan, Cook, Laa (2024).