项目作者: egarpor

项目描述 :
Tests for rotational symmetry on the hypersphere. Software companion for "On optimal tests for rotational symmetry against new classes of hyperspherical distributions"
高级语言: R
项目地址: git://github.com/egarpor/rotasym.git
创建时间: 2019-05-10T08:05:40Z
项目社区:https://github.com/egarpor/rotasym

开源协议:GNU General Public License v3.0

下载


rotasym

License:
GPLv3
R build
status


Overview

Software companion for the paper “On optimal tests for rotational
symmetry against new classes of hyperspherical distributions

(García-Portugués, Paindaveine and Verdebout, 2020). It implements the
proposed tests for rotational symmetry of hyperspherical data and allows
to replicate the data application presented.

Installation

Get the released version from CRAN:

  1. # Install the package
  2. install.packages("rotasym")
  3. # Load package
  4. library(rotasym)

Alternatively, get the latest version from GitHub:

  1. # Install the package
  2. library(devtools)
  3. install_github("egarpor/rotasym")
  4. # Load package
  5. library(rotasym)

Tests usage

The following are some simple examples of the usage of the main function
of the package, test_rotasym, with simulated data. More examples are
available in ?test_rotasym.

  1. # Sample data from a vMF (rotational symmetric distribution about mu)
  2. n <- 200
  3. p <- 10
  4. theta <- c(1, rep(0, p - 1))
  5. set.seed(123456789)
  6. data_0 <- r_vMF(n = n, mu = theta, kappa = 1)

Specified-θ case

  1. # theta known
  2. test_rotasym(data = data_0, theta = theta, type = "sc")
  3. #>
  4. #> Scatter test for rotational symmetry
  5. #>
  6. #> data: data_0
  7. #> Q_sc = 35.013, df = 44, p-value = 0.8315
  8. test_rotasym(data = data_0, theta = theta, type = "loc_vMF")
  9. #>
  10. #> Location vMF test for rotational symmetry
  11. #>
  12. #> data: data_0
  13. #> Q_loc_vMF = 11.316, df = 9, p-value = 0.2547
  14. test_rotasym(data = data_0, theta = theta, type = "hyb_vMF")
  15. #>
  16. #> Hybrid vMF test (addition of statistics) for rotational symmetry
  17. #>
  18. #> data: data_0
  19. #> Q_hyb_vMF = 46.329, df = 53, p-value = 0.7297

Unspecified-θ case

  1. # theta unknown (employs the spherical mean as estimator)
  2. test_rotasym(data = data_0, type = "sc")
  3. #>
  4. #> Scatter test for rotational symmetry
  5. #>
  6. #> data: data_0
  7. #> Q_sc = 36.568, df = 44, p-value = 0.7793
  8. test_rotasym(data = data_0, type = "loc_vMF")
  9. #>
  10. #> Location vMF test for rotational symmetry
  11. #>
  12. #> data: data_0
  13. #> Q_loc_vMF = 12.335, df = 9, p-value = 0.1951
  14. test_rotasym(data = data_0, type = "hyb_vMF")
  15. #>
  16. #> Hybrid vMF test (addition of statistics) for rotational symmetry
  17. #>
  18. #> data: data_0
  19. #> Q_hyb_vMF = 48.902, df = 53, p-value = 0.6344

Data application: test for the rotational symmetry of sunspots

The data application in García-Portugués, Paindaveine and Verdebout
(2020) can be replicated through the script
sunspots-births.R
(data gathering and preprocessing) and the code snippet below.

  1. # Load data
  2. data("sunspots_births")
  3. sunspots_births$X <-
  4. cbind(cos(sunspots_births$phi) * cos(sunspots_births$theta),
  5. cos(sunspots_births$phi) * sin(sunspots_births$theta),
  6. sin(sunspots_births$phi))
  7. # Test rotational symmetry for the 23rd cycle
  8. sunspots_23 <- subset(sunspots_births, cycle == 23)
  9. test_rotasym(data = sunspots_23$X, type = "sc", theta = c(0, 0, 1))
  10. #>
  11. #> Scatter test for rotational symmetry
  12. #>
  13. #> data: sunspots_23$X
  14. #> Q_sc = 3.5964, df = 2, p-value = 0.1656
  15. test_rotasym(data = sunspots_23$X, type = "loc", theta = c(0, 0, 1))
  16. #>
  17. #> Location test for rotational symmetry
  18. #>
  19. #> data: sunspots_23$X
  20. #> Q_loc = 1.5657, df = 2, p-value = 0.4571
  21. test_rotasym(data = sunspots_23$X, type = "hyb", theta = c(0, 0, 1))
  22. #>
  23. #> Hybrid test (addition of statistics) for rotational symmetry
  24. #>
  25. #> data: sunspots_23$X
  26. #> Q_hyb = 5.1622, df = 4, p-value = 0.2711
  27. # Test rotational symmetry for the 22nd cycle
  28. sunspots_22 <- subset(sunspots_births, cycle == 22)
  29. test_rotasym(data = sunspots_22$X, type = "sc", theta = c(0, 0, 1))
  30. #>
  31. #> Scatter test for rotational symmetry
  32. #>
  33. #> data: sunspots_22$X
  34. #> Q_sc = 4.4577, df = 2, p-value = 0.1077
  35. test_rotasym(data = sunspots_22$X, type = "loc", theta = c(0, 0, 1))
  36. #>
  37. #> Location test for rotational symmetry
  38. #>
  39. #> data: sunspots_22$X
  40. #> Q_loc = 8.7579, df = 2, p-value = 0.01254
  41. test_rotasym(data = sunspots_22$X, type = "hyb", theta = c(0, 0, 1))
  42. #>
  43. #> Hybrid test (addition of statistics) for rotational symmetry
  44. #>
  45. #> data: sunspots_22$X
  46. #> Q_hyb = 13.216, df = 4, p-value = 0.01027
  47. # More analyses in ?sunspots_births
  48. example("sunspots_births")
  49. #>
  50. #> snspt_> # Load data
  51. #> snspt_> data("sunspots_births")
  52. #>
  53. #> snspt_> # Transform to Cartesian coordinates
  54. #> snspt_> sunspots_births$X <-
  55. #> snspt_+ cbind(cos(sunspots_births$phi) * cos(sunspots_births$theta),
  56. #> snspt_+ cos(sunspots_births$phi) * sin(sunspots_births$theta),
  57. #> snspt_+ sin(sunspots_births$phi))
  58. #>
  59. #> snspt_> # Plot data associated to the 23rd cycle
  60. #> snspt_> sunspots_23 <- subset(sunspots_births, cycle == 23)
  61. #>
  62. #> snspt_> n <- nrow(sunspots_23$X)
  63. #>
  64. #> snspt_> if (requireNamespace("rgl")) {
  65. #> snspt_+ rgl::plot3d(0, 0, 0, xlim = c(-1, 1), ylim = c(-1, 1), zlim = c(-1, 1),
  66. #> snspt_+ radius = 1, type = "s", col = "lightblue", alpha = 0.25,
  67. #> snspt_+ lit = FALSE)
  68. #> snspt_+ }
  69. #>
  70. #> snspt_> n_cols <- 100
  71. #>
  72. #> snspt_> cuts <- cut(x = sunspots_23$date, include.lowest = TRUE,
  73. #> snspt_+ breaks = quantile(sunspots_23$date,
  74. #> snspt_+ probs = seq(0, 1, l = n_cols + 1)))
  75. #>
  76. #> snspt_> if (requireNamespace("rgl")) {
  77. #> snspt_+ rgl::points3d(sunspots_23$X, col = viridisLite::viridis(n_cols)[cuts])
  78. #> snspt_+ }
  79. #>
  80. #> snspt_> # Spörer's law: sunspots at the beginning of the solar cycle (dark blue
  81. #> snspt_> # color) tend to appear at higher latitudes, gradually decreasing to the
  82. #> snspt_> # equator as the solar cycle advances (yellow color)
  83. #> snspt_>
  84. #> snspt_> # Estimation of the density of the cosines
  85. #> snspt_> V <- cosines(X = sunspots_23$X, theta = c(0, 0, 1))
  86. #>
  87. #> snspt_> h <- bw.SJ(x = V, method = "dpi")
  88. #>
  89. #> snspt_> plot(kde <- density(x = V, bw = h, n = 2^13, from = -1, to = 1), col = 1,
  90. #> snspt_+ xlim = c(-1, 1), ylim = c(0, 3), axes = FALSE, main = "",
  91. #> snspt_+ xlab = "Cosines (latitude angles)", lwd = 2)
  92. #>
  93. #> snspt_> at <- seq(-1, 1, by = 0.25)
  94. #>
  95. #> snspt_> axis(2); axis(1, at = at)
  96. #>
  97. #> snspt_> axis(1, at = at, line = 1, tick = FALSE,
  98. #> snspt_+ labels = paste0("(", 90 - round(acos(at) / pi * 180, 1), "º)"))
  99. #>
  100. #> snspt_> rug(V)
  101. #>
  102. #> snspt_> legend("topright", legend = c("Full cycle", "Initial 25% cycle",
  103. #> snspt_+ "Final 25% cycle"),
  104. #> snspt_+ lwd = 2, col = c(1, viridisLite::viridis(12)[c(3, 8)]))
  105. #>
  106. #> snspt_> # Density for the observations within the initial 25% of the cycle
  107. #> snspt_> part1 <- sunspots_23$date < quantile(sunspots_23$date, 0.25)
  108. #>
  109. #> snspt_> V1 <- cosines(X = sunspots_23$X[part1, ], theta = c(0, 0, 1))
  110. #>
  111. #> snspt_> h1 <- bw.SJ(x = V1, method = "dpi")
  112. #>
  113. #> snspt_> lines(kde1 <- density(x = V1, bw = h1, n = 2^13, from = -1, to = 1),
  114. #> snspt_+ col = viridisLite::viridis(12)[3], lwd = 2)
  115. #>
  116. #> snspt_> # Density for the observations within the final 25% of the cycle
  117. #> snspt_> part2 <- sunspots_23$date > quantile(sunspots_23$date, 0.75)
  118. #>
  119. #> snspt_> V2 <- cosines(X = sunspots_23$X[part2, ], theta = c(0, 0, 1))
  120. #>
  121. #> snspt_> h2 <- bw.SJ(x = V2, method = "dpi")
  122. #>
  123. #> snspt_> lines(kde2 <- density(x = V2, bw = h2, n = 2^13, from = -1, to = 1),
  124. #> snspt_+ col = viridisLite::viridis(12)[8], lwd = 2)
  125. #>
  126. #> snspt_> # Computation the level set of a kernel density estimator that contains
  127. #> snspt_> # at least 1 - alpha of the probability (kde stands for an object
  128. #> snspt_> # containing the output of density(x = data))
  129. #> snspt_> kde_level_set <- function(kde, data, alpha) {
  130. #> snspt_+
  131. #> snspt_+ # Estimate c from alpha
  132. #> snspt_+ c <- quantile(approx(x = kde$x, y = kde$y, xout = data)$y, probs = alpha)
  133. #> snspt_+
  134. #> snspt_+ # Begin and end index for the potentially many intervals in the level sets
  135. #> snspt_+ kde_larger_c <- kde$y >= c
  136. #> snspt_+ run_length_kde <- rle(kde_larger_c)
  137. #> snspt_+ begin <- which(diff(kde_larger_c) > 0) + 1
  138. #> snspt_+ end <- begin + run_length_kde$lengths[run_length_kde$values] - 1
  139. #> snspt_+
  140. #> snspt_+ # Return the [a_i, b_i], i = 1, ..., K in the K rows
  141. #> snspt_+ return(cbind(kde$x[begin], kde$x[end]))
  142. #> snspt_+
  143. #> snspt_+ }
  144. #>
  145. #> snspt_> # Level set containing the 90% of the probability, in latitude angles
  146. #> snspt_> 90 - acos(kde_level_set(kde = kde, data = V, alpha = 0.10)) / pi * 180
  147. #> [,1] [,2]
  148. #> [1,] -29.448244 -2.455986
  149. #> [2,] 2.582017 28.123329
  150. #>
  151. #> snspt_> # Modes (in cosines and latitude angles)
  152. #> snspt_> modes <- c(kde$x[kde$x < 0][which.max(kde$y[kde$x < 0])],
  153. #> snspt_+ kde$x[kde$x > 0][which.max(kde$y[kde$x > 0])])
  154. #>
  155. #> snspt_> 90 - acos(modes) / pi * 180
  156. #> [1] -13.69322 16.49001

References

García-Portugués, E., Paindaveine, D., and Verdebout, T. (2020). On
optimal tests for rotational symmetry against new classes of
hyperspherical distributions. Journal of the American Statistical
Association
, 115(532):1873–1887.
doi:10.1080/01621459.2019.1665527.