Created
September 26, 2024 16:15
-
-
Save SwampThingPaul/dbe9cc664dc79f9584660f81d9cc5ce6 to your computer and use it in GitHub Desktop.
Theil-sen comparison
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library(zyp) | |
library(mblm) | |
# From https://library.virginia.edu/data/articles/theil-sen-regression-programming-and-understanding-an-outlier-resistant-alternative-to-least-squares | |
theil_sen <- function(x,y){ | |
n <- length(x) | |
max_n_slopes <- (n * (n - 1)) / 2 | |
slopes <- vector(mode = 'list', length = max_n_slopes) # list of NULL elements | |
add_at <- 1 | |
# Calculate point-to-point slopes if x_i != x_j | |
for (i in 1:(n - 1)) { | |
slopes_i <- lapply((i + 1):n, function(j) if (x[j] != x[i]) { (y[j] - y[i]) / (x[j] - x[i]) }) | |
slopes[add_at:(add_at + length(slopes_i) - 1)] <- slopes_i | |
add_at <- add_at + length(slopes_i) | |
} | |
# Calculate Theil-Sen slope | |
slopes <- unlist(slopes) # drop NULL elements (indefinite slopes/unfilled list entries) | |
theil_sen_slope <- median(slopes, na.rm = TRUE) | |
# Calculate Theil-Sen intercept | |
intercepts <- y - (theil_sen_slope * x) | |
theil_sen_intercept <- median(intercepts, na.rm = TRUE) | |
# Return | |
c('Theil-Sen intercept' = theil_sen_intercept, 'Theil-Sen slope' = theil_sen_slope) | |
} | |
set.seed(123) | |
# Generate linear data | |
x <- 1:100 | |
y <- 2*x + rnorm(100, 0, 10) | |
# Add some outliers | |
y[c(10, 30, 50, 70, 90)] <- y[c(10, 30, 50, 70, 90)] + 50 | |
plot(y~x) | |
zyp.mod <- zyp.sen(y~x) | |
zyp.mod | |
mblm.mod <- mblm(y~x,repeated = F) | |
summary(mblm.mod) | |
UV.theilsen <- theil_sen(x,y) | |
UV.theilsen |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment