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==