Una de las mejores cosas de R es que programar es muy sencillo. Y eso es bueno, porque la manipulación de datos, el análisis, o la visualización se convierten en tareas más sencillas cuando uno puede escribir pequeñas funciones. Además, dado que R es de código abierto, puedes inspeccionar lo que hace cada una de las funciones, con lo que es importante saber un poco de programación con el objetivo de poder entender bién qué hace cada cosa.

Definir funciones

Podemos pensar en una función como una forma de empaquetar operaciones en una expresión reusable. Por ejemplo, consideramos un caso sencillo en el que quisiésemos calcular la media de una variable. En lugar de calcular sum sobre length en cada situación, podríamos simplemente empaquetar esas dos operaciones y darles un nombre:

my_mean <- function(x) sum(x)/length(x)
my_mean(c(0, 1))

Como vemos, para definir una función, usamos la palabra clave function seguida de paréntesis y (opcionalmente), los argumentos que toma la función. En el cuerpo, incluimos la expresión que la función ejecutará. A esta instrucción le podemos asignar un nombre: en este caso, my_mean.

Veamos cómo podemos ahora ver los contenidos que acabamos de definir.

my_mean

La expresión que hemos escrito es válida, pero podemos ser más explícitos si introducimos las instrucciones entre llaves e indicamos que la expresión es lo que queremos que la función retorne.

my_mean <- function(x) {
  return(sum(x)/length(x))
}

Veamos ahora algunas estructuras de control:

Iteraciones

for nos permite iterar y repetir operaciones a lo largo de una secuencia. Como podéis imaginar, eso implica ser explícitos sobre dos cosas: la secuencia y la variable que tomará valores sobre esa secuencia.

for (i in 1:3) print(i)

Veamos un ejemplo menos trivial:

myvector <- c(1, 2, 3, 4)
out <- 0
for (i in 1:length(myvector)) {
  out <- myvector[i] + out
}
out

Aquí el vector out mantendrá el resultado de acumular progresivamente los resultados de aplicar transformaciones sobre myvector myvector. Tened en cuenta como i toma, en cada iteración, un valor a lo largo de las posiciones de myvector que vamos usando para atravesar el objeto paso a paso.

Podemos empaquetar estas operaciones en una función:

my_sum <- function(x) {
  out <- 0
  for (i in 1:length(x)) {
    out <- x[i] + out
  }
  return(out)
}
my_sum(c(1, 2, 3, 4))

Otra forma de construir iteraciones es con while. Evaluará una expresión hasta que la condición que ésta defina no sea TRUE.

i <- 0
while (i < 3) {
  print(i)
  i <- i + 1
}

Como podéis ver, la condición i < 3 pasa a ser FALSE en la tercera iteración, con lo que 3 no se imprime en pantalla.

Hay casos en los que el uso de which es natural, como por ejemplo cuando no sabemos cuántas iteraciones tenemos que hacer. Por ejemplo, en el caso de algoritmos que queremos que corran hasta que hayan convergido. Tomemos por ejemplo el cálculo del método de Newton-Raphson para minimizar la función \(x^2\).

tol <- 0.01
x_last <- 10; diff <- 1
while (abs(diff) > tol) {
    x <- x_last - (x_last^2)/(2*x_last)
    diff <- (x - x_last)
    x_last <- x
    print(x)
}

Es obvio decirlo, pero es importante tener cuidado con while para no acabar produciendo iteraciones infinitas.

Conditionales

Como podéis imaginar, los condicionales ejecutan una operación dependiendo del valor (TRUE o FALSE) de una expresión. En R usan la siguiente sintaxis:

if (x > 0) {
  print("It's positive") 
} else if (x == 0) {
  print("It's neither positive nor negative")
} else {
  print("It's negative")
}

que podemos empaquetar en una función:

my_sign <- function(x) {
  if (x > 0) {
    out <- "It's positive!"
  } else if (x == 0) {
    out <- "It's neither positive nor negative!"
  } else {
    out <- "It's negative!"
  }
  return(out)
}

y podemos usar esta expresión para ilustrar qué ocurriría si no somos cuidados en los detalles de la programación:

my_sign("A cow")

¿Cómo gestionar este tipo de errores? Elevando un error:

my_sign <- function(x) {
  if (!is.numeric(x)) {
    stop("Input is not a number")
  }
  
  if (x > 0) {
    out <- "It's positive!"
  } else if (x == 0) {
    out <- "It's neither positive nor negative!"
  } else {
    out <- "It's negative!"
  }
  return(out)
}

Dos cosas que debemos resaltar aquí. Primero, que el operador ! es el operador negación (TRUE == !FALSE). Segundo, que stop interrumpe la evaluación y produce un error, con lo que la función no llega al segundo condicional.

LS0tIAp0aXRsZTogIkZ1bmRhbWVudG9zIGRlIHByb2dyYW1hY2nDs24iCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVCICVkLCAlWScpYCIKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRSwgY2FjaGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChldmFsID0gRkFMU0UpCmtuaXRyOjpvcHRzX2NodW5rJHNldChmaWcucGF0aCA9ICcuL2Fzc2V0cy8nKQpgYGAKClVuYSBkZSBsYXMgbWVqb3JlcyBjb3NhcyBkZSBgUmAgZXMgcXVlIHByb2dyYW1hciBlcyBtdXkgc2VuY2lsbG8uIFkgZXNvIGVzCmJ1ZW5vLCBwb3JxdWUgbGEgbWFuaXB1bGFjacOzbiBkZSBkYXRvcywgZWwgYW7DoWxpc2lzLCBvIGxhIHZpc3VhbGl6YWNpw7NuIHNlCmNvbnZpZXJ0ZW4gZW4gdGFyZWFzIG3DoXMgc2VuY2lsbGFzIGN1YW5kbyB1bm8gcHVlZGUgZXNjcmliaXIgcGVxdWXDsWFzIGZ1bmNpb25lcy4KQWRlbcOhcywgZGFkbyBxdWUgYFJgIGVzIGRlIGPDs2RpZ28gYWJpZXJ0bywgcHVlZGVzIGluc3BlY2Npb25hciBsbyBxdWUgaGFjZSBjYWRhCnVuYSBkZSBsYXMgZnVuY2lvbmVzLCBjb24gbG8gcXVlIGVzIGltcG9ydGFudGUgc2FiZXIgdW4gcG9jbyBkZSBwcm9ncmFtYWNpw7NuIGNvbgplbCBvYmpldGl2byBkZSBwb2RlciBlbnRlbmRlciBiacOpbiBxdcOpIGhhY2UgY2FkYSBjb3NhLgoKIyMjIERlZmluaXIgZnVuY2lvbmVzCgpQb2RlbW9zIHBlbnNhciBlbiB1bmEgZnVuY2nDs24gY29tbyB1bmEgZm9ybWEgZGUgZW1wYXF1ZXRhciBvcGVyYWNpb25lcyBlbiB1bmEKZXhwcmVzacOzbiByZXVzYWJsZS4gUG9yIGVqZW1wbG8sIGNvbnNpZGVyYW1vcyB1biBjYXNvIHNlbmNpbGxvIGVuIGVsIHF1ZQpxdWlzacOpc2Vtb3MgY2FsY3VsYXIgbGEgbWVkaWEgZGUgdW5hIHZhcmlhYmxlLiBFbiBsdWdhciBkZSBjYWxjdWxhciBgc3VtYCBzb2JyZQpgbGVuZ3RoYCBlbiBjYWRhIHNpdHVhY2nDs24sIHBvZHLDrWFtb3Mgc2ltcGxlbWVudGUgZW1wYXF1ZXRhciBlc2FzIGRvcwpvcGVyYWNpb25lcyB5IGRhcmxlcyB1biBub21icmU6CgpgYGB7cn0KbXlfbWVhbiA8LSBmdW5jdGlvbih4KSBzdW0oeCkvbGVuZ3RoKHgpCm15X21lYW4oYygwLCAxKSkKYGBgCgpDb21vIHZlbW9zLCBwYXJhIGRlZmluaXIgdW5hIGZ1bmNpw7NuLCB1c2Ftb3MgbGEgcGFsYWJyYSBjbGF2ZSBgZnVuY3Rpb25gIHNlZ3VpZGEKZGUgcGFyw6ludGVzaXMgeSAob3BjaW9uYWxtZW50ZSksIGxvcyBhcmd1bWVudG9zIHF1ZSB0b21hIGxhIGZ1bmNpw7NuLiBFbiBlbApjdWVycG8sIGluY2x1aW1vcyBsYSBleHByZXNpw7NuIHF1ZSBsYSBmdW5jacOzbiBlamVjdXRhcsOhLiBBIGVzdGEgaW5zdHJ1Y2Npw7NuIGxlCnBvZGVtb3MgYXNpZ25hciB1biBub21icmU6IGVuIGVzdGUgY2FzbywgYG15X21lYW5gLgoKVmVhbW9zIGPDs21vIHBvZGVtb3MgYWhvcmEgdmVyIGxvcyBjb250ZW5pZG9zIHF1ZSBhY2FiYW1vcyBkZSBkZWZpbmlyLgoKYGBge3J9Cm15X21lYW4KYGBgCgpMYSBleHByZXNpw7NuIHF1ZSBoZW1vcyBlc2NyaXRvIGVzIHbDoWxpZGEsIHBlcm8gcG9kZW1vcyBzZXIgbcOhcyBleHBsw61jaXRvcyBzaQppbnRyb2R1Y2ltb3MgbGFzIGluc3RydWNjaW9uZXMgZW50cmUgbGxhdmVzIGUgaW5kaWNhbW9zIHF1ZSBsYSBleHByZXNpw7NuIGVzIGxvCnF1ZSBxdWVyZW1vcyBxdWUgbGEgZnVuY2nDs24gcmV0b3JuZS4KCmBgYHtyfQpteV9tZWFuIDwtIGZ1bmN0aW9uKHgpIHsKICByZXR1cm4oc3VtKHgpL2xlbmd0aCh4KSkKfQpgYGAKClZlYW1vcyBhaG9yYSBhbGd1bmFzIGVzdHJ1Y3R1cmFzIGRlIGNvbnRyb2w6CgojIyMgSXRlcmFjaW9uZXMKCmBmb3JgIG5vcyBwZXJtaXRlIGl0ZXJhciB5IHJlcGV0aXIgb3BlcmFjaW9uZXMgYSBsbyBsYXJnbyBkZSB1bmEgc2VjdWVuY2lhLiBDb21vCnBvZMOpaXMgaW1hZ2luYXIsIGVzbyBpbXBsaWNhIHNlciBleHBsw61jaXRvcyBzb2JyZSBkb3MgY29zYXM6IGxhIHNlY3VlbmNpYSB5IGxhCnZhcmlhYmxlIHF1ZSB0b21hcsOhIHZhbG9yZXMgc29icmUgZXNhIHNlY3VlbmNpYS4gCgpgYGB7cn0KZm9yIChpIGluIDE6MykgcHJpbnQoaSkKYGBgCgpWZWFtb3MgdW4gZWplbXBsbyBtZW5vcyB0cml2aWFsOgoKYGBge3J9Cm15dmVjdG9yIDwtIGMoMSwgMiwgMywgNCkKb3V0IDwtIDAKZm9yIChpIGluIDE6bGVuZ3RoKG15dmVjdG9yKSkgewogIG91dCA8LSBteXZlY3RvcltpXSArIG91dAp9Cm91dApgYGAKCkFxdcOtIGVsIHZlY3RvciAgYG91dGAgbWFudGVuZHLDoSBlbCByZXN1bHRhZG8gZGUgYWN1bXVsYXIgcHJvZ3Jlc2l2YW1lbnRlIGxvcwpyZXN1bHRhZG9zIGRlIGFwbGljYXIgdHJhbnNmb3JtYWNpb25lcyBzb2JyZSBgbXl2ZWN0b3JgCmBteXZlY3RvcmAuIFRlbmVkIGVuIGN1ZW50YSBjb21vIGBpYCB0b21hLCBlbiBjYWRhIGl0ZXJhY2nDs24sIHVuIHZhbG9yIGEgbG8KbGFyZ28gZGUgbGFzIHBvc2ljaW9uZXMgZGUgIGBteXZlY3RvcmAgcXVlIHZhbW9zIHVzYW5kbyBwYXJhIGF0cmF2ZXNhciBlbCBvYmpldG8KcGFzbyBhIHBhc28uCgpQb2RlbW9zIGVtcGFxdWV0YXIgZXN0YXMgb3BlcmFjaW9uZXMgZW4gdW5hIGZ1bmNpw7NuOgpgYGB7cn0KbXlfc3VtIDwtIGZ1bmN0aW9uKHgpIHsKICBvdXQgPC0gMAogIGZvciAoaSBpbiAxOmxlbmd0aCh4KSkgewogICAgb3V0IDwtIHhbaV0gKyBvdXQKICB9CiAgcmV0dXJuKG91dCkKfQpteV9zdW0oYygxLCAyLCAzLCA0KSkKYGBgCgpPdHJhIGZvcm1hIGRlIGNvbnN0cnVpciBpdGVyYWNpb25lcyBlcyBjb24gIGB3aGlsZWAuIEV2YWx1YXLDoSB1bmEgZXhwcmVzacOzbgpoYXN0YSBxdWUgbGEgY29uZGljacOzbiBxdWUgw6lzdGEgZGVmaW5hIG5vIHNlYSBgVFJVRWAuCgpgYGB7cn0KaSA8LSAwCndoaWxlIChpIDwgMykgewogIHByaW50KGkpCiAgaSA8LSBpICsgMQp9CmBgYAoKQ29tbyBwb2TDqWlzIHZlciwgbGEgY29uZGljacOzbiBgaSA8IDNgICBwYXNhIGEgc2VyIGBGQUxTRWAgZW4gbGEgdGVyY2VyYQppdGVyYWNpw7NuLCBjb24gbG8gcXVlIGAzYCBubyBzZSBpbXByaW1lIGVuIHBhbnRhbGxhLgoKSGF5IGNhc29zIGVuIGxvcyBxdWUgZWwgdXNvIGRlIGB3aGljaGAgZXMgbmF0dXJhbCwgY29tbyBwb3IgZWplbXBsbyBjdWFuZG8gbm8Kc2FiZW1vcyBjdcOhbnRhcyBpdGVyYWNpb25lcyB0ZW5lbW9zIHF1ZSBoYWNlci4gUG9yIGVqZW1wbG8sIGVuIGVsIGNhc28gZGUKYWxnb3JpdG1vcyBxdWUgcXVlcmVtb3MgcXVlIGNvcnJhbiBoYXN0YSBxdWUgaGF5YW4gY29udmVyZ2lkby4gIFRvbWVtb3MgcG9yCmVqZW1wbG8gZWwgY8OhbGN1bG8gZGVsIG3DqXRvZG8gZGUgTmV3dG9uLVJhcGhzb24gcGFyYSBtaW5pbWl6YXIgbGEgZnVuY2nDs24gJHheMiQuCgpgYGB7cn0KdG9sIDwtIDAuMDEKeF9sYXN0IDwtIDEwOyBkaWZmIDwtIDEKd2hpbGUgKGFicyhkaWZmKSA+IHRvbCkgewogICAgeCA8LSB4X2xhc3QgLSAoeF9sYXN0XjIpLygyKnhfbGFzdCkKICAgIGRpZmYgPC0gKHggLSB4X2xhc3QpCiAgICB4X2xhc3QgPC0geAogICAgcHJpbnQoeCkKfQpgYGAKCkVzIG9idmlvIGRlY2lybG8sIHBlcm8gZXMgaW1wb3J0YW50ZSB0ZW5lciBjdWlkYWRvIGNvbiBgd2hpbGVgIHBhcmEgbm8gYWNhYmFyCnByb2R1Y2llbmRvIGl0ZXJhY2lvbmVzIGluZmluaXRhcy4KCiMjIyBDb25kaXRpb25hbGVzCgpDb21vIHBvZMOpaXMgaW1hZ2luYXIsICBsb3MgY29uZGljaW9uYWxlcyBlamVjdXRhbiB1bmEgb3BlcmFjacOzbiBkZXBlbmRpZW5kbyBkZWwKdmFsb3IgKGBUUlVFYCBvIGBGQUxTRWApIGRlIHVuYSBleHByZXNpw7NuLiBFbiBgUmAgdXNhbiBsYSBzaWd1aWVudGUgc2ludGF4aXM6CgpgYGB7ciBldmFsPUZBTFNFfQppZiAoeCA+IDApIHsKICBwcmludCgiSXQncyBwb3NpdGl2ZSIpIAp9IGVsc2UgaWYgKHggPT0gMCkgewogIHByaW50KCJJdCdzIG5laXRoZXIgcG9zaXRpdmUgbm9yIG5lZ2F0aXZlIikKfSBlbHNlIHsKICBwcmludCgiSXQncyBuZWdhdGl2ZSIpCn0KYGBgCgpxdWUgcG9kZW1vcyBlbXBhcXVldGFyIGVuIHVuYSBmdW5jacOzbjoKYGBge3J9Cm15X3NpZ24gPC0gZnVuY3Rpb24oeCkgewogIGlmICh4ID4gMCkgewogICAgb3V0IDwtICJJdCdzIHBvc2l0aXZlISIKICB9IGVsc2UgaWYgKHggPT0gMCkgewogICAgb3V0IDwtICJJdCdzIG5laXRoZXIgcG9zaXRpdmUgbm9yIG5lZ2F0aXZlISIKICB9IGVsc2UgewogICAgb3V0IDwtICJJdCdzIG5lZ2F0aXZlISIKICB9CiAgcmV0dXJuKG91dCkKfQpgYGAKCnkgcG9kZW1vcyB1c2FyIGVzdGEgZXhwcmVzacOzbiBwYXJhIGlsdXN0cmFyIHF1w6kgb2N1cnJpcsOtYSBzaSBubyBzb21vcyBjdWlkYWRvcwplbiBsb3MgZGV0YWxsZXMgZGUgbGEgcHJvZ3JhbWFjacOzbjoKYGBge3J9Cm15X3NpZ24oIkEgY293IikKYGBgCgrCv0PDs21vIGdlc3Rpb25hciBlc3RlIHRpcG8gZGUgZXJyb3Jlcz8gRWxldmFuZG8gdW4gZXJyb3I6CgpgYGB7cn0KbXlfc2lnbiA8LSBmdW5jdGlvbih4KSB7CiAgaWYgKCFpcy5udW1lcmljKHgpKSB7CiAgICBzdG9wKCJJbnB1dCBpcyBub3QgYSBudW1iZXIiKQogIH0KICAKICBpZiAoeCA+IDApIHsKICAgIG91dCA8LSAiSXQncyBwb3NpdGl2ZSEiCiAgfSBlbHNlIGlmICh4ID09IDApIHsKICAgIG91dCA8LSAiSXQncyBuZWl0aGVyIHBvc2l0aXZlIG5vciBuZWdhdGl2ZSEiCiAgfSBlbHNlIHsKICAgIG91dCA8LSAiSXQncyBuZWdhdGl2ZSEiCiAgfQogIHJldHVybihvdXQpCn0KYGBgCgpEb3MgY29zYXMgcXVlIGRlYmVtb3MgcmVzYWx0YXIgYXF1w60uIFByaW1lcm8sIHF1ZSBlbCBvcGVyYWRvciBgIWAgZXMgZWwgb3BlcmFkb3IgbmVnYWNpw7NuIChgVFJVRSA9PQohRkFMU0VgKS4gIFNlZ3VuZG8sIHF1ZSBgc3RvcGAgaW50ZXJydW1wZSBsYSBldmFsdWFjacOzbiB5IHByb2R1Y2UgdW4gZXJyb3IsIGNvbgpsbyBxdWUgbGEgZnVuY2nDs24gbm8gbGxlZ2EgYWwgc2VndW5kbyBjb25kaWNpb25hbC4KCg==