Programación

Escalabilidad (y estructuras cooperativas)

Esta entrada es una breve nota (en parte, para mí) sobre On the Scalability of Cooperative Structures, un artículo sobre lo que el título indica (sí, que existen estructuras cooperativas como, p.e., las cooperativas o determinados sistemas políticos defendidos desde ciertas posiciones ideológicas, que tienen muy serios problemas de escalabilidad) y que a pesar de su interés no cabría en estas páginas si no fuese por este parrafito:

What I would like to do, instead, is introduce a concept to the discussion that I believe has the potential to elucidate several aspects in an extremely helpful way. The concept is that of “scalability.” It is drawn from the computer science literature, and it refers rather generally to the capacity of a system to take on increased workload by integrating additional resources (i.e. to “scale up”) without suffering degradation of performance.

x[] <- lapply(...)

R

Estos días he aprendido una expresión muy compacta para operar sobre las columnas de una tabla en R:

x <- iris # por ejemplo
x[] <- lapply(x, function(x) factor(x)) # o cualquier otra función

Aunque lapply debería devolver (y, de hecho, devuelve) una lista, esos corchetes de x fuerzan de una manera contraintuitiva que la salida final sea una tabla.

La magia es consecuencia de que [<- es una función en sí misma (puedes consultar help("[<-") si quieres) con un comportamiento que es el que es (porque sí, a veces las cosas son simplemente como son).

De texto a función

R

Problema: convertir una expresión definida por un usuario (p.e., algo como "a+b") en una función (i.e., function(a, b) a + b).

Solución:

    gen_foo <- function(expr){
        my_args <- all.vars(parse(text = expr))
        expr <- paste0("function(",
                       paste(my_args, collapse = ","),
                       ") ", expr)
        eval(parse(text = expr))
    }

Demostración:

    multiplica <- gen_foo("a * b")
    multiplica(5, 31)

BLAS, eficiencia y lme4

Cada cierto número de años me reencuentro con la cuestión de BLAS, ATLAS y todas esas cosas por tratar de arañar un poco de eficiencia a R.

Existen el BLAS de toda la vida que, parece ser, viene de serie con R y uno puede optar por otras versiones optimizadas como ATLAS u OpenBLAS, cuyas ventajas relativas, de acuerdo con estos benchmarks, no parecen demasiado claras.

Lo novedoso en esta revisita al problema es que he aprendido que a los anteriores se han sumado en estos últimos años, cuando menos:

Modas y fotogenia del código secuencial

R

Este tipo de programación se puso de moda en los noventa:

Y yo decía: ¿dónde están mis bucles? ¿Y mis bifurcaciones?

Este tipo de programación está de moda últimamente:

hourly_delay <- flights %>%
  filter(!is.na(dep_delay)) %>%
  group_by(date, hour) %>%
  summarise(
    delay = mean(dep_delay),
    n = n() ) %>%
  filter(n > 10)

Y todo bien, sí, pero sigo sin tener bucles o bifurcaciones.

Tal vez no hagan falta. Al menos, para cosas de andar por casa. Pero, lo confieso, el código de verdad que escribo está lleno de casos especiales, comprobaciones de todo tipo de contingencias, reglas que aplican a unas columnas sí y otras no, objetos complejos (p.e., listas), que se van rellenando de una u otra manera dependiendo de las opciones del usuario y otras enojosas coyunturas muy reñidas con la elegancia.

Cerebros "hackeados"

Tengo delante Los cerebros ‘hackeados’ votan de Harari, autor de cierta y reciente fama. Elabora sobre un argumento simple y manido: el cerebro funciona como un ordenador y los seres humanos somos no solo perfectamente predecibles sino también perfectamente manipulables. De lo que se derivan muchas funestas consecuencias en lo político y en lo social.

El artículo me ha sido recomendado por dos personas cuyo criterio tengo en muy alta estima. Pero otra lo ha criticado con saña aquí.

Documentar como el culo, no pensar en el usuario final, ser incapaz de ponerte en su situación, etc.

R

De vez en cuando pruebo paquetes promisorios. No es infrecuente que cosas que he intentado hace años, algún ejemplo más o menos sencillo que he publicado aquí, acabe convirtiéndose en la piedra angular de algo facturable. Incluso de algo facturable por mí.

geozoning podía haber sido uno de esos. La promesa del paquete es que puede ayudarte a segmentar regiones del espacio de acuerdo con alguna variable, una especie de clústering para información de tipo espacial.

Cuidado con los $

R

El otro día tropecé con el siguiente artefacto:

a <- list(aa = 12, bb = 14)
is.null(a$a)
#[1] FALSE
a$a
#[1] 12

No es un bug de R, porque la documentación reza:

x$name is equivalent to x[[“name”, exact = FALSE]]

Y se pueden contrastar:

a[["a", exact = FALSE]]
a[["a", exact = TRUE]]

Comentarios:

  • Odio muchísimo los bugs que no son bugs porque están documentados en la nota ‡2.a.(c), párrafo §23.3 de la sección 14 de un manual oscuro.
  • Odio mucho a los gilipollas que se complacen en mandarte a leer manuales.
  • Odio mucho las violaciones del principio de mínima sorpresa.
  • Soy consciente de que R es, fundamentalmente, una plataforma de análisis interactivo y no (o solo subsidiariamente) un lenguaje de programación.
  • Soy consciente de que muchos de los defaults de R se decidieron antes de que se popularizasen los completadores de comandos.