Nothing
# test-intermediate_output.R — Tests for intermediate output calculations
#
# These tests verify the CQA scoring, residual computation, and contribution
# column logic used in Step 6 (Download Estimated Sale Prices & Residuals).
# The actual server.R code is reactive, so we test the underlying logic
# independently.
test_that("CQA scoring ranks residuals correctly", {
# CQA = proportion of comps with smaller residual * 10
residuals_val <- c(NA, -200, -100, 0, 100, 200) # row 1 = subject (NA)
comp_resid <- residuals_val[-1L]
n_comps <- sum(!is.na(comp_resid))
cqa_all <- vapply(residuals_val, function(r) {
if (is.na(r)) return(NA_real_)
sum(comp_resid < r, na.rm = TRUE) / n_comps * 10
}, numeric(1))
expect_true(is.na(cqa_all[1])) # subject is NA
expect_equal(cqa_all[2], 0) # lowest residual
expect_equal(cqa_all[6], 8) # highest (4/5 * 10)
# CQA should be monotonically increasing with residual
expect_true(all(diff(cqa_all[-1]) >= 0))
})
test_that("CQA per-SF scoring works with living area", {
residuals_val <- c(NA, -200, -100, 0, 100, 200)
living_area <- c(2000, 1500, 1800, 2000, 1600, 2200)
resid_sf <- residuals_val / living_area
comp_resid_sf <- resid_sf[-1L]
n_comps_sf <- sum(!is.na(comp_resid_sf))
cqa_sf <- vapply(resid_sf, function(r) {
if (is.na(r)) return(NA_real_)
sum(comp_resid_sf < r, na.rm = TRUE) / n_comps_sf * 10
}, numeric(1))
expect_true(is.na(cqa_sf[1]))
# Values should be between 0 and 10
expect_true(all(cqa_sf[-1] >= 0 & cqa_sf[-1] <= 10))
})
test_that("contribution columns sum to prediction", {
# Simulate: basis + contributions should equal prediction
result <- fit_earth(mtcars, target = "mpg",
predictors = c("wt", "hp", "cyl"))
model <- result$model
eq <- format_model_equation(result)
groups <- eq$groups
# Extract intercept
basis <- 0
contrib_groups <- list()
for (grp in groups) {
if (grp$degree == 0L) {
basis <- grp$terms[[1]]$coefficient
} else {
contrib_groups <- c(contrib_groups, list(grp))
}
}
# Compute contributions
pred_df <- result$data
predicted <- as.numeric(predict(model, newdata = pred_df))
total_contrib <- rep(basis, nrow(pred_df))
for (grp in contrib_groups) {
contrib <- earthUI:::eval_g_function_(model, grp, pred_df)
total_contrib <- total_contrib + contrib
}
# basis + sum(contributions) should equal prediction
expect_equal(total_contrib, predicted, tolerance = 0.01)
})
test_that("residual = actual - predicted", {
result <- fit_earth(mtcars, target = "mpg",
predictors = c("wt", "hp"))
predicted <- as.numeric(predict(result$model, newdata = result$data))
actual <- result$data$mpg
residuals_val <- actual - predicted
expect_equal(length(residuals_val), nrow(result$data))
# Sum of residuals should be near zero for earth models
expect_true(abs(mean(residuals_val)) < 1)
})
test_that("calc_residual verification column matches residual", {
result <- fit_earth(mtcars, target = "mpg",
predictors = c("wt", "hp"))
model <- result$model
eq <- format_model_equation(result)
groups <- eq$groups
pred_df <- result$data
predicted <- as.numeric(predict(model, newdata = pred_df))
actual <- pred_df$mpg
# Compute contributions
basis <- 0
total_contrib <- numeric(nrow(pred_df))
for (grp in groups) {
if (grp$degree == 0L) {
basis <- grp$terms[[1]]$coefficient
} else {
contrib <- earthUI:::eval_g_function_(model, grp, pred_df)
total_contrib <- total_contrib + contrib
}
}
calc_residual <- actual - (basis + total_contrib)
direct_residual <- actual - predicted
expect_equal(calc_residual, direct_residual, tolerance = 0.01)
})
test_that("ranking columns are in correct order", {
# Verify the expected column ordering logic
ranking_cols <- c("residual_sf", "cqa_sf", "residual", "cqa")
other_cols <- c("street_address", "sale_price", "living_sqft")
# Simulate reordering
all_cols <- c(other_cols, ranking_cols)
df <- as.data.frame(matrix(0, nrow = 3, ncol = length(all_cols)))
names(df) <- all_cols
available <- intersect(ranking_cols, names(df))
remaining <- setdiff(names(df), available)
reordered <- c(available, remaining)
expect_equal(reordered[1:4], ranking_cols)
expect_equal(reordered[5:7], other_cols)
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.