R version 3.0.1 (2013-05-16) -- "Good Sport" Copyright (C) 2013 The R Foundation for Statistical Computing Platform: x86_64-w64-mingw32/x64 (64-bit) When I update a formula by removing a variable that is not there, the result is identical with the original formula: > update(y ~ x, . ~ . - w) y ~ x This makes sense to me! > Now, I do the same with a more complex formula: > (myFormula <- as.formula(paste(c("y ~ x0", paste0("x", 1:30)), collapse = "+"))) y ~ x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19 + x20 + x21 + x22 + x23 + x24 + x25 + x26 + x27 + x28 + x29 + x30 > (update(myFormula, . ~ . - w1)) y ~ x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19 + x20 + x21 + x22 + x23 + x24 + x25 + x26 + x27 + x28 + x29 + x30 - 1 # Intercept is removed -> ??? > Worse: > (updateArgument <- as.formula(paste(c(". ~ . ", paste0("w", 1:20)), collapse = " - "))) . ~ . - w1 - w2 - w3 - w4 - w5 - w6 - w7 - w8 - w9 - w10 - w11 - w12 - w13 - w14 - w15 - w16 - w17 - w18 - w19 - w20 > update(myFormula, updateArgument) y ~ x0 + x1 + x2 + x3 + x4 + x5 + x6 + x8 + x9 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19 + x20 + x23 + x24 + x25 + x26 + x27 + x28 + x29 + x30 + x7:w1 + x10:w1 + x21:w2:w8:w9:w10:w12:w14:w17:w18 + x22:w2:w8:w9:w10:w12:w14:w17:w18 - 1 > # When I run the code reapeatedly, the results may differ, but is always wrong

I see this on OSX as well. Obviously, there's a bug, apparent inside terms.formula, specifically in terms <- .External(C_termsform, x, specials, data, keep.order, allowDotAsName) where x is y ~ (x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19 + x20 + x21 + x22 + x23 + x24 + x25 + x26 + x27 + x28 + x29 + x30) - w1 - w2 - w3 - w4 - w5 - w6 - w7 - w8 - w9 - w10 - w11 - w12 - w13 - w14 - w15 - w16 - w17 - w18 - w19 - w20 attr(,".Environment") <environment: R_GlobalEnv>

It's quite prosaic. That formula has 32 variables, and the code forgot about the intercept in its internal bitmap allocation. So the 32nd variable got aliased with the intercept.