Sto provando a creare una versione più parsimoniosa della soluzione this, che comporta l'indicazione dell'RHS di una formula nel formato d1 + d1:d2
.Definizione di un operatore infisso per l'uso all'interno di una formula
Dato che *
nel contesto di una formula è una concisa stand-in per la piena interazione (cioè d1 * d2
dà d1 + d2 + d1:d2
), il mio approccio è stato quello di cercare di definire un operatore alternativo, dire %+:%
utilizzando l'approccio infisso ho abituati a in altre applicazioni, alla:
"%+:%" <- function(d1,d2) d1 + d2 + d1:d2
Tuttavia, questo non riesce prevedibilmente, perché non sono stato attento a valutazione; introduciamo un esempio per illustrare il mio progresso:
set.seed(1029)
v1 <- runif(1000)
v2 <- runif(1000)
y <- .8*(v1 < .3) + .2 * (v2 > .25 & v2 < .8) -
.4 * (v2 > .8) + .1 * (v1 > .3 & v2 > .8)
Con questo esempio, si spera che sia chiaro il motivo per cui semplicemente scrivendo i due termini potrebbe essere indesiderabile:
y ~ cut(v2, breaks = c(0, .25, .8, 1)) +
cut(v2, breaks = c(0, .25, .8, 1)):I(v1 < .3)
Una soluzione che è vicino alla mia uscita desiderata è quello di definire l'intera formula in funzione:
plus.times <- function(outvar, d1, d2){
as.formula(paste0(quote(outvar), "~", quote(d1),
"+", quote(d1), ":", quote(d2)))
}
Questo dà i coefficienti previsti quando passato a lm
, ma con nomi che un re più difficile da interpretare direttamente (soprattutto nei dati reali in cui ci prendiamo cura di dare d1
e d2
nomi descrittivi, in contrasto con questo esempio generico):
out1 <- lm(y ~ cut(v2, breaks = c(0, .25, .8, 1)) +
cut(v2, breaks = c(0, .25, .8, 1)):I(v1 < .3))
out2 <- lm(plus.times(y, cut(v2, breaks = c(0, .25, .8, 1)), I(v1 < .3)))
any(out1$coefficients != out2$coefficients)
# [1] FALSE
names(out2$coefficients)
# [1] "(Intercept)" "d1(0.25,0.8]" "d1(0.8,1]" "d1(0,0.25]:d2TRUE"
# [5] "d1(0.25,0.8]:d2TRUE" "d1(0.8,1]:d2TRUE"
Quindi questo non è ottimale.
C'è un modo per definire la regolazione del codice in modo che l'operatore di infissi sopra menzionato funzioni come previsto? Che ne dici di alterare la forma di plus.times
in modo che le variabili non vengano rinominate?
ho rovistando (?formula
, ?"~"
, ?":"
, getAnywhere(formula.default)
, this risposta, ecc), ma non ho visto come esattamente R interpreta *
quando è incontrato in una formula in modo che possa fare i miei piccoli aggiustamenti desiderati .
vengono interpretati previsti ::: model.frame.default in c https://github.com/wch/r-source/blob/ed66b715221d2720f5b334470335635bada520b1/src/library/stats/src/model.c#L888 – rawr
@rawr grazie. non posso dire di avere idea di cosa stia succedendo nel codice C - vedo che "definiscono" ciascuno dei simboli compresi da 'formula', ma sembrano usare solo' tildeSymbol'. Questo significa comunque che non sarò in grado di ottenere il mio infisso senza andare a finire in C & definendo, ad esempio 'plusColonSymbol' come si fa qui? – MichaelChirico
@ La risposta di HeatherTurner sembra esattamente giusta per me. Se vuoi davvero iniziare a scherzare con le formule espandibili, ti suggerirei di iniziare (1) guardando il componente 'terms' dei risultati di' model.frame() 'e (2) guardando il codice [qui] (https : //github.com/glmmTMB/glmmTMB/blob/master/glmmTMB/R/utils.R) ... –