Trucos

La regla del tres (para estimar la probabilidad de un evento todavía no observado)

Me acusan (quien lo hizo, si me lee, sabrá identificarse) de repetirme, de contar una historia dos, y sino me paran los pies, tres y más veces. Ya me pasó una vez por aquí. Espero que no me esté volviendo a suceder hoy porque habría jurado haber mencionado este asunto antes.

Es el de la estimación de la probabilidad de eventos todavía no observados. Traduzco y (como no rectoreo universidad pública alguna y, por ende, no puedo permitirme el lujo de copiar sin citar) luego diré de donde:

R es un vago

Si creo la función

foo <- function(a,b) a*a + b

y la llamo mediante

foo(1 + 1,3)

pueden ocurrir dos cosas: o bien que R precalcule 1+1 y la función ejecute 2 * 2 + 3 o bien que la función ejecute directamente (1+1)*(1+1)+3. Pero, ¿qué es lo que hace realmente? Si escribimos

f1 <- function(x){
    print("Soy f1")
    x
}

f2 <- function(x){
    print("Soy f2")
    x
}

foo(f1(2), f2(3))

obtenemos

> foo(f1(2), f2(3))
[1] "Soy f1"
[1] "Soy f2"
[1] 7

lo que significa que f1 ha sido llamada una única vez. Es decir, R resuelve sus argumentos antes de aplicar la función. Pero hay más:

Cosas de R (¿que tal vez alguien sabrá explicar?)

R

En Twitter, leo

The state of the art in statistical computing:

sum(c(1, 2), na.r=F) [1] 3 sum(c(1, 2), na.r=T) [1] 4

– John Myles White (@johnmyleswhite) September 8, 2015

¿Alguien puede explicar lo que ocurre? ¿Es tan grade como parece indicar sorna el autor del tuit?

Mejores mensajes de error con deparse + substitute

R
foo <- function(df, column.name){
    if (!column.name %in% colnames(df))
      stop("Column ", column.name, " not found in ", deparse(substitute(df)))

    mean(df$column.name)  # por ejemplo
  }

  foo(iris, "petal.area")

Lanza el error

Error in foo(iris, "petal.area") : Column petal.area not found in iris

mucho más informativo gracias a deparse + substitute.

Todos contra todos

R

¿Cómo se suman los cuadrados de un vector de números en un paradigma tradicional de programación? Se crea un bucle que lo recorre y que guarda las sumas parciales en un acumulador. Sumamente económico en términos de memoria: apenas consume unos pocos bytes en la pila. La versión funcional de la cosa se parece más a sum(x^2), que implica generar un vector de cuadrados y dilapidar memoria.

Así las cosas, en C uno tiende a recorrer y construir resultados parciales. R invita a crear estructuras de datos preprocesados y aplicar sobre ellas funciones resumen. Map y reduce, si se quiere.

Dónde guardar los paquetes de R (en Linux, al menos)

R

En todos mis Linux, desde el principio de los tiempos, R guardaba los paquetes en

  • /usr/lib/R/library
  • /usr/lib/R/site-library (¡a veces y no sé por qué!)
  • /usr/local/lib/R/site-library

Bajo /usr/lib deberían instalarse solo aquellos que vienen de serie con la instalación de R (o que se instalan usando el sistema de actualización de paquetes de la distribución de Linux) mientras que bajo /usr/local vivirían los instalados posteriormente por el usuario (véase esto).

Por supuesto, para escribir /usr/local/lib/R/site-library hacen falta permisos de superusuario y los paquetes ahí instalados están disponibles para todos los usuarios de la máquina. Pero de un tiempo a esta parte y por culpa, creo, de RStudio (tanto en versión de escritorio como de servidor), se me han comenzado a instalar paquetes en ~/R, bajo mi directorio personal. ¡Anatema!

Primer elemento de un grupo dentro de un dataframe de R

R

Hoy he encontrado una solución decente a un problema que venía arrastrando desde hace un tiempo en R. Tengo una tabla muy grande (decenas de millones de registros) con su id. Me interesa quedarme con el subconjunto de la tabla original en que para cada id el valor de una determinada variable es mínimo.

Un caso de uso: esa variable adicional mide la distancia de la observación a los centroides de unos clústers. El registro con el menor valor proporciona la asignación del sujeto a su grupo.

Reetiquetar factores en R

R

La operación que voy a discutir hoy es una que plantea problemas a muchos programadores nuevos en R: cómo renombrar niveles de un factor. Un caso típico ocurre al leer una tabla que contiene datos no normalizados. Por ejemplo,

mi.factor <- factor( c("a", "a", "b", "B", "A") )

donde se entiende que a y A, b y B son la misma cosa. Otro caso similar ocurre cuando se quieren agrupar niveles poco frecuentes como en

mi.factor <- factor(c(rep("a", 1000), rep("b", 500), letters[3:10]))

Para homogeneizar la entrada se recomienda sustituir sobre levels(mi.factor) así:

Eles, "casts" y el rizo del rizo de la programación eficiente (con R)

R

Ante las preguntas de alguno de mis lectores, voy a proporcionar una explicación acerca de la misteriosa L. Bueno, voy más bien a dejar que la deduzcan ellos mismos a partir de la siguiente serie de bloques de código:

a <- rep( 0, 10 )
typeof( a )
object.size( a )

b <- rep( 0L, 10 )
typeof( b )
object.size( b )

##############

a <- 1:10
typeof( a )
object.size( a )

a[1] <- 10
typeof( a )
object.size( a )

a <- 1:10
a[1] <- 10L
typeof( a )
object.size( a )

##############

a <- 1:10
tracemem( a )
a[1] <- 2

a <- 1:10
tracemem( a )
a[1] <- 2L

##############

system.time( replicate( 1e5, { a <- (1:100); a[1] <- 12  } ) )
system.time( replicate( 1e5, { a <- (1:100); a[1] <- 12L } ) )

Lectores míos, no seáis perezosos y haced, cuando menos, ?tracemem en vuestra consola. Una vez leída la página de ayuda, ¿se os ocurre algún truco para ahorrar mucha memoria cuando trabajáis con objetos (p.e., matrices) grandes de enteros?

La función monotonic de PROC SQL de SAS

Previamente he hablado en este blog de las ventajas que ofrece PROC SQL en SAS sobre otros métodos más propiamente SAS de realizar ciertas manipulaciones de datos. Existen no obstante cierto tipo de manipulaciones que exigen pasos data: gran parte de las que hacen uso de la variable automática n.

No obstante, existe una función no documentada de SAS que permite implementar con SQL muchas operaciones de este tipo: monotonic.

¿Puedo cambiar mi código retroactivamente?

R

La verdad, me gustaría, Me gustaría volver atrás y modificar algunas docenas de código en R que malescribí como un diletante por no estar al tanto de una función de R cuya verdadera utilidad descubrí recientemente (gracias le sean dadas, de nuevo, a Jorge Iván Vélez).

La verdad, no tengo excusa. Incluso se habló de ella en nuestro blog hermano.

Y es que nunca me había percatado de la potencia de la función mapply. He aquí el problema: se tienen dos listas de la misma longitud y se quieren transformar los objetos de la primera en función de datos extraídos de los objetos correspondientes de la segunda. En los tiempos oscuros que duraron hasta anteayer, me veía abocado a utilizar un bucle que llevase la contabilidad del índice para poder recorrer ambas listas simultáneamente: