Trucos

El principio de mediocridad como instrumento para estimar duraciones

Esta entrada trata de explicar cómo utilizar el llamado principio de mediocridad para la estimación de la duración de cosas cuando apenas se sabe nada al respecto. En ese sentido, extiende y fundamente lo que puede leerse aquí.

Planteamiento

Consideremos el conjunto $A$ de todos los pares de números (reales, que todo hay que decirlo) $0 < a < b$.

En todo lo que sigue, $b$ se interpretará como la duración total de algo (la existencia de la especie humana, el número de semanas que una obra teatral estará en cartel, etc.) y $a$ el momento en el que un observador ha contemplado la existencia de ese algo.

Un viejo truco para que R vuele

R

Existe un viejo truco —mas no por ello conocido— para que R vuele. Lo aprendí en una conferencia de uno de los padres de R (aunque ya no recuerdo quién era) en la primera década del siglo. El problema que tenía entre manos era el de ajustar unos cuantos miles de regresiones logísticas. Además de hacer uso de los métodos de paralelización, aún muy rudimentarios en la época, uno de los trucos más efectivos que utilizaba era el de desnudar las funciones.

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)

Más sobre factores, strings y ordenación

R

Esta entrada debería ser un comentario más en esta otra, pero voy a abusar del privilegio de ser dueño de la plataforma para promocionarla.

Voy a decir cosas que son aproximadamente ciertas. Los detalles de la verdad de todo están en la ayuda y el código de sort y sus métodos.

En R hay dos métodos de ordenación: shell y radix. El primero es genérico y el segundo es mejor cuando en el vector hay muchos elementos repetidos (p.e., ordenar el censo por provincias).

Hagan sus apuestas; luego, corran el siguiente código

R
library(microbenchmark)
library(ggplot2)

a_int <- sample(10:99, 1e6, replace = T)
a_char <- paste("P", a_int, sep = "")

res <- microbenchmark(
    sort_int  = sort(a_int),
    sort_char_radix = sort(a_char, method = "radix"),
    sort_char = sort(a_char),
    factor_trick = as.character(sort(as.factor(a_char))),
    times = 50
)

autoplot(res)

Nota para mí: usar flextable, usar flextable

R

De aquí a cuando lo tenga que usar realmente, seguro que me olvido. Así que retomo el uso original de este blog, que era el de dejarme notas a mí mismo y apunto: usa [flextable`](https://cran.r-project.org/package=flextable).

¿Y por qué?, me preguntaré a mí mismo dentro de unos días. Pues por cosas como esta:

(Claro está, salvo que alguien tenga a bien proponer una alternativa mejor).

Evaluación de trucos para multiplicaciones aproximadas

En Street Fighting Mathematics (leedlo) hay un capítulo en el que se discuten trucos para realizar mental y aproximadamente operaciones del tipo 3600 × 4.4 × 10^4 × 32.

La recomendación es la siguiente: contar ceros primero, gestionar las cifras significativas después. En el caso anterior, el autor identifica 8 ceros (tres del 3600, cuatro del 10^4 y uno del 32), quedando como cifras significativas 3.6, 4.4 y 3.2.

Para estas últimas, recomienda aproximarlas a 1, pocos (alrededor de 3) y 10. Pocos es una cifra que vale tres y cuyo cuadrado es 10. Por lo tanto, 3.6 × 4.4 × 3.2 es el cubo de pocos, es decir, treinta. De manera que la aproximación de 3600 × 4.4 × 10^4 × 32 es un tres seguido de nueve ceros (en realidad, es un cinco seguido de nueve ceros).

Funcionalidades infravaloradas de R: los corchetes

R

[Ad]Mirad esta pequeña maravilla de código:

n <- 100
dat <- data.frame(
  y = rnorm(100),
  x = sample(letters[1:3], n, replace = T)
  )

medias <- tapply(dat$y, dat$x, mean)
dat$x.trans <- medias[dat$x]

head(dat)

El corchete está manifiestamente infravalorado.

Que Magritte me perdone

R

¿Qué es %>%? ¿Para qué sirve? Hoy he hecho la presentación más sesgada y parcial del operador para neófitos en R:

library(magrittr)

8 %>% sin %>% exp
exp(sin(8))

(Es que madrugar me pone de mal humor y saca mi más sincero yo de dentro de mí mismo).

Cuantiles, sí, pero ¿de qué tipo?

Porque resulta que los hay de varios tipos. En R, hasta nueve de ellos:

    set.seed(1234)
    muestra <- sort(rt(100, 3))
    mis.cuantiles <- sapply(1:9, function(tipo) quantile(muestra, 0.834, type = tipo))
    mis.cuantiles
    #    83.4%     83.4%     83.4%     83.4%     83.4%     83.4%     83.4%     83.4%     83.4%
    #0.9065024 0.9065024 0.8951710 0.8997036 0.9053693 0.9331290 0.9015846 0.9077920 0.9063154

Las definiciones de todos ellos pueden consultarse en Sample Quantiles in Statistical Packages.

Las diferencias entre ellos, de todos modos, decrecen conforme aumenta el tamaño muestral:

n.obs <- seq(100, 1e5, by = 1e3)
res <- sapply(n.obs, function(n){
  x <- rt(n, 3)
  diff(range(sapply(1:9, function(tipo)
    quantile(x, 0.834, type = tipo))))
})

plot(n.obs, log10(res), type = "l",
  xlab = "n obs", ylab = "discrepancia",
  main = "Diferencias entre los distintos tipos de cuantiles")

Una mala manera de perder un par de horas

R

Es esta:

156.67 * 100
# 15667
as.integer(156.67 * 100)
#15666

Claro, hay que leer ?as.integer para enterarte de que, en realidad, la función que quieres usar es round.

Una mala manera de perder un par de horas.