Nothing
# test-rca_calculations.R — Tests for RCA calculation logic
#
# The RCA code lives in server.R but the core math (CQA interpolation,
# adjustment computation) can be tested independently.
test_that("CQA interpolation produces correct subject residual", {
# Simulate comp CQA/residual pairs
cqa_sorted <- c(0, 2, 4, 6, 8, 10)
resid_sorted <- c(-50000, -30000, -10000, 10000, 30000, 50000)
# User CQA = 5.0 should interpolate between idx 3 (4,-10000) and idx 4 (6,10000)
user_cqa <- 5.0
subject_resid <- stats::approx(cqa_sorted, resid_sorted,
xout = user_cqa, rule = 2)$y
expect_equal(subject_resid, 0) # midpoint between -10000 and 10000
# CQA = 0 should give lowest residual
expect_equal(
stats::approx(cqa_sorted, resid_sorted, xout = 0, rule = 2)$y,
-50000
)
# CQA = 10 should give highest residual
expect_equal(
stats::approx(cqa_sorted, resid_sorted, xout = 10, rule = 2)$y,
50000
)
})
test_that("CQA interpolation clamps at extremes (rule=2)", {
cqa_sorted <- c(1, 3, 5, 7, 9)
resid_sorted <- c(-20000, -10000, 0, 10000, 20000)
# Below range: should clamp to lowest
below <- stats::approx(cqa_sorted, resid_sorted, xout = 0, rule = 2)$y
expect_equal(below, -20000)
# Above range: should clamp to highest
above <- stats::approx(cqa_sorted, resid_sorted, xout = 10, rule = 2)$y
expect_equal(above, 20000)
})
test_that("subject_value = est + interpolated residual", {
predicted_subject <- 450000
subject_resid_total <- 12000
subject_est <- predicted_subject + subject_resid_total
expect_equal(subject_est, 462000)
})
test_that("CQA per-SF converts residual correctly", {
# When use_sf = TRUE, interpolated value is per-SF, multiply by living_area
subject_resid_per_sf <- 5.0 # $5/sqft
subject_la <- 2000
subject_resid_total <- subject_resid_per_sf * subject_la
expect_equal(subject_resid_total, 10000)
})
test_that("adjustment = subject contribution - comp contribution", {
subj_contrib <- c(sale_age = 5000, living_sqft = 80000, age = -8000)
comp_contrib <- c(sale_age = 3000, living_sqft = 72000, age = -10000)
adjustments <- subj_contrib - comp_contrib
expect_equal(adjustments[["sale_age"]], 2000)
expect_equal(adjustments[["living_sqft"]], 8000)
expect_equal(adjustments[["age"]], 2000)
})
test_that("net_adjustments = sum of all adjustments + residual_adjustment", {
adjustments <- c(2000, 8000, 2000)
residual_adj <- 5000
net <- sum(adjustments) + residual_adj
expect_equal(net, 17000)
})
test_that("gross_adjustments = sum of absolute adjustments", {
adjustments <- c(2000, -8000, 2000)
residual_adj <- -5000
gross <- sum(abs(adjustments)) + abs(residual_adj)
expect_equal(gross, 17000)
})
test_that("adjusted_sale_price = sale_price + net_adjustments", {
sale_price <- 500000
net_adj <- -12000
adjusted <- sale_price + net_adj
expect_equal(adjusted, 488000)
})
test_that("residual_adjustment = subject_resid - comp_resid", {
subject_resid_total <- 8000
comp_residuals <- c(5000, -3000, 12000, 0)
resid_adj <- subject_resid_total - comp_residuals
expect_equal(resid_adj, c(3000, 11000, -4000, 8000))
})
test_that("weight-0 rows get subject_value = est + subject_resid", {
predicted <- c(450000, 480000, 520000, 500000, 460000)
subject_resid_total <- 10000
zero_wt <- c(3, 5) # rows with weight = 0
sv <- predicted[zero_wt] + subject_resid_total
expect_equal(sv, c(530000, 470000))
})
test_that("percentage columns compute correctly", {
actual <- c(500000, 480000, 520000)
net_adj <- c(0, -12000, 8000)
gross_adj <- c(0, 25000, 18000)
resid_adj <- c(0, 5000, -3000)
net_pct <- round(net_adj / actual, 4)
gross_pct <- round(gross_adj / actual, 4)
resid_pct <- round(resid_adj / actual, 4)
expect_equal(net_pct[2], round(-12000 / 480000, 4))
expect_equal(gross_pct[2], round(25000 / 480000, 4))
expect_equal(resid_pct[3], round(-3000 / 520000, 4))
})
test_that("RCA with real earth model produces consistent results", {
# End-to-end: fit model, compute contributions, verify adjustments
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
contrib_list <- list()
for (grp in groups) {
if (grp$degree == 0L) {
basis <- grp$terms[[1]]$coefficient
} else {
label <- gsub(" ", "_", grp$label)
contrib <- earthUI:::eval_g_function_(model, grp, pred_df)
contrib_list[[label]] <- contrib
}
}
# Subject = row 1, comp = row 2
for (label in names(contrib_list)) {
adj <- contrib_list[[label]][1] - contrib_list[[label]][2]
# Adjustment should be finite
expect_true(is.finite(adj))
}
# Net adjustments: sum of variable adjustments + residual adjustment
residuals_val <- actual - predicted
resid_adj_1_vs_2 <- residuals_val[1] - residuals_val[2]
total_var_adj <- sum(vapply(contrib_list, function(c) c[1] - c[2], numeric(1)))
net_adj <- total_var_adj + resid_adj_1_vs_2
# adjusted_sale_price = actual[2] + net_adj should equal actual[1]
adjusted_sp <- actual[2] + net_adj
expect_equal(adjusted_sp, actual[1], tolerance = 0.01)
})
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.