From d7cbd39e333b387f32a6338955d98dc7eaedfb85 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sat, 15 Aug 2026 04:14:21 +0000 Subject: [PATCH] Optimize ifelse calls in llcont.glm binomial family Replaced two `ifelse` calls with direct division and vectorized conditional reassignment in the `binomial` switch case inside `llcont.glm`. This avoids evaluating both true and false branches entirely before subsetting. --- .jules/bolt.md | 4 ++++ R/llcont.R | 8 ++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index f658475..ea1cb9d 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -15,3 +15,7 @@ ## 2024-05-15 - [R Performance: ifelse Overhead] **Learning:** In R, ifelse evaluates both true and false branches entirely before subsetting, which is very inefficient for vector operations. **Action:** Optimize this by preallocating with res <- Y * 0 to preserve attributes and using vectorized subsetting like if any cond res subset <- ... + +## 2024-05-16 - Safe ifelse Optimization with Mathematical Operations in R +**Learning:** While replacing `ifelse(n == 0, 0, y/n)` with pre-allocation (`y_res <- y * 0; y_res[cond] <- ...`) works, it can be mathematically simplified to `y_res <- y / n; y_res[n == 0 & !is.na(n)] <- 0`. The key learning is that subsetting *must* explicitly check `!is.na(n)` to avoid throwing a fatal "NAs are not allowed in subscripted assignments" error if `n` contains missing values, making the code safer and more readable. +**Action:** When replacing `ifelse` via mathematical shortcuts, always combine the logical condition with `& !is.na(...)` to preserve NA handling robustly. diff --git a/R/llcont.R b/R/llcont.R index d8e496a..7c191a3 100644 --- a/R/llcont.R +++ b/R/llcont.R @@ -53,12 +53,16 @@ llcont.glm <- function(x, ...){ if(is.matrix(y)) { ## Bolt: replaced apply(..., 1, sum) with optimized rowSums() for performance n <- rowSums(y) - y <- ifelse(n == 0, 0, y[, 1]/n) + ## Bolt: optimized ifelse for performance + y <- y[, 1] / n + y[n == 0 & !is.na(n)] <- 0 } else { n <- rep.int(1, length(y)) } m <- if (any(n > 1)) n else wt - wt <- ifelse(m > 0, (wt/m), 0) + ## Bolt: optimized ifelse for performance + wt <- wt / m + wt[m <= 0 & !is.na(m)] <- 0 dbinom(round(m * y), round(m), mpreds, log = TRUE) * wt }, quasibinomial = {