From ce47b60285828af859ed4fc8828a6c3dd583e44b Mon Sep 17 00:00:00 2001 From: Dominique Makowski Date: Mon, 24 Jun 2024 13:11:43 +0100 Subject: [PATCH 1/6] add docs #374 --- R/smoothness.R | 15 ++++++++++++++- man/smoothness.Rd | 15 +++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/R/smoothness.R b/R/smoothness.R index b45202b5f..28c2f4a0e 100644 --- a/R/smoothness.R +++ b/R/smoothness.R @@ -1,4 +1,10 @@ -#' Quantify the smoothness of a vector +#' Series smoothness +#' +#' Functions to quantify the smoothness of a vector, which can be used in some cases +#' as an index of "linearity". A smooth series is one that does not have abrupt changes in +#' its values. The smoothness of a series can be measured in different ways, such +#' as the standard deviation of the standardized differences or the lag-one +#' autocorrelation. #' #' @param x Numeric vector (similar to a time series). #' @param method Can be `"diff"` (the standard deviation of the standardized @@ -12,6 +18,13 @@ #' plot(x) #' smoothness(x, method = "cor") #' smoothness(x, method = "diff") +#' +#' # A boootstrapped value can also be computed +#' smoothness(x, iterations = 100) +#' +#' # When perfectly linear, the "smoothness" is 1 +#' smoothness(1:10) +#' #' @return Value of smoothness. #' @references https://stats.stackexchange.com/questions/24607/how-to-measure-smoothness-of-a-time-series-in-r #' diff --git a/man/smoothness.Rd b/man/smoothness.Rd index f2e1d2662..5b93db2b5 100644 --- a/man/smoothness.Rd +++ b/man/smoothness.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/smoothness.R \name{smoothness} \alias{smoothness} -\title{Quantify the smoothness of a vector} +\title{Series smoothness} \usage{ smoothness(x, method = "cor", lag = 1, iterations = NULL, ...) } @@ -24,13 +24,24 @@ errors. If \code{NULL} (default), parametric standard errors are computed.} Value of smoothness. } \description{ -Quantify the smoothness of a vector +Functions to quantify the smoothness of a vector, which can be used in some cases +as an index of "linearity". A smooth series is one that does not have abrupt changes in +its values. The smoothness of a series can be measured in different ways, such +as the standard deviation of the standardized differences or the lag-one +autocorrelation. } \examples{ x <- (-10:10)^3 + rnorm(21, 0, 100) plot(x) smoothness(x, method = "cor") smoothness(x, method = "diff") + +# A boootstrapped value can also be computed +smoothness(x, iterations = 100) + +# When perfectly linear, the "smoothness" is 1 +smoothness(1:10) + } \references{ https://stats.stackexchange.com/questions/24607/how-to-measure-smoothness-of-a-time-series-in-r From e0e98949051ec639a87f153ffe305bd813b16f43 Mon Sep 17 00:00:00 2001 From: Dominique Makowski Date: Mon, 24 Jun 2024 17:39:25 +0100 Subject: [PATCH 2/6] fix diff method (breaking) --- R/smoothness.R | 9 +++++++-- man/smoothness.Rd | 6 +++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/R/smoothness.R b/R/smoothness.R index 28c2f4a0e..7adbc45e6 100644 --- a/R/smoothness.R +++ b/R/smoothness.R @@ -2,7 +2,7 @@ #' #' Functions to quantify the smoothness of a vector, which can be used in some cases #' as an index of "linearity". A smooth series is one that does not have abrupt changes in -#' its values. The smoothness of a series can be measured in different ways, such +#' its values. The smoothness of a series can be approximated in different ways, such #' as the standard deviation of the standardized differences or the lag-one #' autocorrelation. #' @@ -25,6 +25,10 @@ #' # When perfectly linear, the "smoothness" is 1 #' smoothness(1:10) #' +#' # And closer to zero for random +#' smoothness(rnorm(1000)) +#' smoothness(rnorm(1000), method = "diff") +#' #' @return Value of smoothness. #' @references https://stats.stackexchange.com/questions/24607/how-to-measure-smoothness-of-a-time-series-in-r #' @@ -54,7 +58,8 @@ smoothness.numeric <- function(x, if (method == "cor") { smooth <- stats::cor(utils::head(x, length(x) - lag), utils::tail(x, length(x) - lag)) } else { - smooth <- stats::sd(diff(x, lag = lag)) / abs(mean(diff(x, lag = lag))) + diff <- standardize(diff(x)) + smooth <- 1 - mean((diff(diff) ** 2) / 4) # Note the reversal to match the other method } if (!is.null(iterations)) { diff --git a/man/smoothness.Rd b/man/smoothness.Rd index 5b93db2b5..7d7d208be 100644 --- a/man/smoothness.Rd +++ b/man/smoothness.Rd @@ -26,7 +26,7 @@ Value of smoothness. \description{ Functions to quantify the smoothness of a vector, which can be used in some cases as an index of "linearity". A smooth series is one that does not have abrupt changes in -its values. The smoothness of a series can be measured in different ways, such +its values. The smoothness of a series can be approximated in different ways, such as the standard deviation of the standardized differences or the lag-one autocorrelation. } @@ -42,6 +42,10 @@ smoothness(x, iterations = 100) # When perfectly linear, the "smoothness" is 1 smoothness(1:10) +# And closer to zero for random +smoothness(rnorm(1000)) +smoothness(rnorm(1000), method = "diff") + } \references{ https://stats.stackexchange.com/questions/24607/how-to-measure-smoothness-of-a-time-series-in-r From e605941c25c034531bcca101df923926c219f003 Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 27 Jun 2024 13:16:50 +0200 Subject: [PATCH 3/6] Update R/smoothness.R Co-authored-by: Etienne Bacher <52219252+etiennebacher@users.noreply.github.com> --- R/smoothness.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/smoothness.R b/R/smoothness.R index 7adbc45e6..4a7a81b2e 100644 --- a/R/smoothness.R +++ b/R/smoothness.R @@ -19,7 +19,7 @@ #' smoothness(x, method = "cor") #' smoothness(x, method = "diff") #' -#' # A boootstrapped value can also be computed +#' # A bootstrapped value can also be computed #' smoothness(x, iterations = 100) #' #' # When perfectly linear, the "smoothness" is 1 From feb39af21d06ba2444fcc8d5f28db3ac94c0bed2 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 27 Nov 2024 17:50:46 +0100 Subject: [PATCH 4/6] fix tests --- tests/testthat/test-distributions.R | 2 +- tests/testthat/test-smoothness.R | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/testthat/test-distributions.R b/tests/testthat/test-distributions.R index 39d06d957..9605b73c1 100644 --- a/tests/testthat/test-distributions.R +++ b/tests/testthat/test-distributions.R @@ -7,6 +7,6 @@ test_that("distributions", { expect_equal(kurtosis(x)$Kurtosis, -0.1119534, tolerance = 0.01) expect_equal(skewness(x)$Skewness, -5.881466e-17, tolerance = 0.01) - expect_equal(as.numeric(smoothness(x, "diff")), 1.183699, tolerance = 0.01) + expect_equal(as.numeric(smoothness(x, "diff")), 0.9409494, tolerance = 0.01) expect_equal(as.numeric(smoothness(x, "cor")), 0.9979799, tolerance = 0.01) }) diff --git a/tests/testthat/test-smoothness.R b/tests/testthat/test-smoothness.R index 07a81c07b..e7d2f48c1 100644 --- a/tests/testthat/test-smoothness.R +++ b/tests/testthat/test-smoothness.R @@ -2,7 +2,7 @@ test_that("smoothness works", { set.seed(123) x <- (-10:10)^3 + rnorm(21, 0, 100) expect_equal(smoothness(x)[[1]], 0.9030014, tolerance = 0.001) - expect_equal(smoothness(x, method = "auto")[[1]], 1.750452, tolerance = 0.001) + expect_equal(smoothness(x, method = "auto")[[1]], 0.5131369, tolerance = 0.001) }) test_that("smoothness works with iterations", { @@ -11,7 +11,7 @@ test_that("smoothness works with iterations", { set.seed(123) x <- (-10:10)^3 + rnorm(21, 0, 100) expect_equal(smoothness(x, iterations = 100)[[1]], 0.9030014, tolerance = 0.001) - expect_equal(smoothness(x, method = "auto", iterations = 100)[[1]], 1.750452, tolerance = 0.001) + expect_equal(smoothness(x, method = "auto", iterations = 100)[[1]], 0.5131369, tolerance = 0.001) }) From 309d92931b58c71c3c4560fd290a82e8371ea9f0 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 27 Nov 2024 18:00:48 +0100 Subject: [PATCH 5/6] news, desc --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index b75f96278..588bfd4eb 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: datawizard Title: Easy Data Wrangling and Statistical Transformations -Version: 0.13.0.15 +Version: 0.13.0.16 Authors@R: c( person("Indrajeet", "Patil", , "patilindrajeet.science@gmail.com", role = "aut", comment = c(ORCID = "0000-0003-1995-6531")), From b420e97106b64fa4273149f4484d65cf8ce32d1a Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 27 Nov 2024 18:02:52 +0100 Subject: [PATCH 6/6] lintr --- NEWS.md | 3 +++ R/smoothness.R | 31 +++++++++++++++---------------- man/smoothness.Rd | 2 +- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/NEWS.md b/NEWS.md index a701ba2b8..05213ac3b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,9 @@ BREAKING CHANGES * Argument `drop_na` in `data_match()` is deprecated now. Please use `remove_na` instead. +* The `"diff"` method in `smoothness()` was revised and now has a reversed + interpretation. Documentation was updated accordingly. (#374). + CHANGES * The `select` argument, which is available in different functions to select diff --git a/R/smoothness.R b/R/smoothness.R index 4a7a81b2e..d63407973 100644 --- a/R/smoothness.R +++ b/R/smoothness.R @@ -56,16 +56,14 @@ smoothness.numeric <- function(x, } if (method == "cor") { - smooth <- stats::cor(utils::head(x, length(x) - lag), utils::tail(x, length(x) - lag)) + smooth_value <- stats::cor(utils::head(x, length(x) - lag), utils::tail(x, length(x) - lag)) } else { diff <- standardize(diff(x)) - smooth <- 1 - mean((diff(diff) ** 2) / 4) # Note the reversal to match the other method + smooth_value <- 1 - mean((diff(diff) ** 2) / 4) # Note the reversal to match the other method } if (!is.null(iterations)) { - if (!requireNamespace("boot", quietly = TRUE)) { - insight::format_warning("Package 'boot' needed for bootstrapping SEs.") - } else { + if (requireNamespace("boot", quietly = TRUE)) { results <- boot::boot( data = x, statistic = .boot_smoothness, @@ -74,12 +72,14 @@ smoothness.numeric <- function(x, lag = lag ) out_se <- stats::sd(results$t, na.rm = TRUE) - smooth <- data.frame(Smoothness = smooth, SE = out_se) + smooth_value <- data.frame(Smoothness = smooth_value, SE = out_se) + } else { + insight::format_warning("Package 'boot' needed for bootstrapping SEs.") } } - class(smooth) <- unique(c("parameters_smoothness", class(smooth))) - smooth + class(smooth_value) <- unique(c("parameters_smoothness", class(smooth_value))) + smooth_value } @@ -89,14 +89,13 @@ smoothness.data.frame <- function(x, lag = 1, iterations = NULL, ...) { - .smoothness <- - lapply( - x, - smoothness, - method = method, - lag = lag, - iterations = iterations - ) + .smoothness <- lapply( + x, + smoothness, + method = method, + lag = lag, + iterations = iterations + ) .smoothness <- cbind(Parameter = names(.smoothness), do.call(rbind, .smoothness)) class(.smoothness) <- unique(c("parameters_smoothness", class(.smoothness))) .smoothness diff --git a/man/smoothness.Rd b/man/smoothness.Rd index 7d7d208be..9b0b380a9 100644 --- a/man/smoothness.Rd +++ b/man/smoothness.Rd @@ -36,7 +36,7 @@ plot(x) smoothness(x, method = "cor") smoothness(x, method = "diff") -# A boootstrapped value can also be computed +# A bootstrapped value can also be computed smoothness(x, iterations = 100) # When perfectly linear, the "smoothness" is 1