Exemples fàcils de Non standard evaluation

No sé si us heu fixat que hi ha funcions que cal passar arguments en cometes, a vegades sense, d’altres cal un vector i n’hi ha que amb el nom del camp ja n’hi ha prou.

Per entendre el que vull dir, amb un exemple serà més fàcil:

data(cars)

subset(cars, cars$speed < 10 & cars$dist < 10)

  speed dist
1     4    2
3     7    4


subset(cars, speed < 10 & dist < 10)

  speed dist
1     4    2
3     7    4

Tot i que en els dos casos obtenim el mateix resultat, la forma d’arribar és diferent. En el primer cas cal fer cars$ abans de cada camp i en el segon en tenim prou amb els noms dels camps. La funció subset fa ús en el segon cas de non standard evaluation. Si volem programar una funció que usa molts camps, pot ser pràctic utilitzar aquesta tècnica.

Amb aquesta entrada vull mostrar exemples simples de programar funcions que usen non standard evaluation. Cal tenir present que aquestes funcions estan pensades per a un ús interactiu. Per tant, si es volen incloure dins d’altres funcions, podrien sorgir complicacions o problemes.

Com tot exemple simple, serveix bàsicament per mostrar la potencialitat del mateix.

data(cars)

cars$var <- cars$speed * 2

evalVar <- function(dades, var) {

    nom_var <- deparse(substitute(var))
    resultat <- dades[, nom_var]
    resultat
}

evalVar(cars, speed)

 [1]  4  4  7  7  8  9 10 10 10 11 11 12 12 12 12 13 13 13 13 14 14 14 14
[24] 15 15 15 16 16 17 17 17 18 18 18 18 19 19 19 20 20 20 20 20 22 23 24
[47] 24 24 24 25

evalVar(cars, dist)

 [1]   2  10   4  22  16  10  18  26  34  17  28  14  20  24  28  26  34
[18]  34  46  26  36  60  80  20  26  54  32  40  32  40  50  42  56  76
[35]  84  36  46  68  32  48  52  56  64  66  54  70  92  93 120  85

evalCond <- function(dades, cond) {

    cond <- substitute(cond)
    resultat <- eval(cond, dades, parent.frame())
    resultat
}

evalCond(cars, speed + dist)

 [1]   6  14  11  29  24  19  28  36  44  28  39  26  32  36  40  39  47
[18]  47  59  40  50  74  94  35  41  69  48  56  49  57  67  60  74  94
[35] 102  55  65  87  52  68  72  76  84  88  77  94 116 117 144 110

evalCond(cars, speed + dist < var)

 [1]  TRUE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[12] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[23] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[34] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[45] FALSE FALSE FALSE FALSE FALSE FALSE

evalFormula <- function(dades, form) {

    form <- as.formula(form)
    lm(form, dades)

}

evalFormula(cars, speed ~ var)


Call:
lm(formula = form, data = dades)

Coefficients:
(Intercept)          var  
   4.02e-15     5.00e-01  

evalFormula(cars, speed ~ dist)


Call:
lm(formula = form, data = dades)

Coefficients:
(Intercept)         dist  
      8.284        0.166  

Tags: , , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: