Que la fuerza de R también te acompañe a ti (allá a donde haya datos)
La fuerza de R siepre me acompaña allá donde tengo datos. De ello da fe la siguiente captura de pantalla de mi móvil:
Si quieres que también te acompañe a ti:
La fuerza de R siepre me acompaña allá donde tengo datos. De ello da fe la siguiente captura de pantalla de mi móvil:
Si quieres que también te acompañe a ti:
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:
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:
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?
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
.
¿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.
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!
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.
Un truco para generar variables aleatorias normales: sumar doce uniformes y restar seis.
En efecto,
x <- replicate(1000, sum(runif(12)) - 6)
qqnorm(x)
qqline(x, col=2)
produce
Ayuda a entender el motivo que la varianza de la distribución uniforme es 1/12 y que su media es 1/2.
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í:
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?
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.
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: