Con tiempo: encuentro de usuarios de R de Latinoamérica en enero de 2019
Pues sí, acabo de enterarme de que se organiza la tal cosa. Toda la información, escasa de momento, aquí.
Pues sí, acabo de enterarme de que se organiza la tal cosa. Toda la información, escasa de momento, aquí.
Cayeron en mis manos unos datos que no puedo publicar, pero me atreveré a presentar algunos resultados anonimizados. Se trata de una tabla de puntuaciones numéricas (18 en total, cada una en su columna) proporcionadas por unos cuantos centenares de sujetos (filas). Era de interés un estudio cualitativo de las posibles relaciones de dependencia entre las variables.
La manera más rápida de comenzar, un heatmap(cor(dat))
, para obtener
Y luego PCA y todas esas cosas.
Con motivo de fin de año se ha hablado de fallecidos en accidentes de tráfico como por ejemplo en El Mundo o en El País. Y sí, parece que el número observado de muertos ha aumentado.
Lo cual es mucho menos relevante de lo que se da a entender. Si tiras una moneda al aire 100 veces y sacas 48 caras y luego repites el experimento, podrías sacar 53 (y habría aumentado el número observado de caras) o 45 (y habría disminuido). Lo relevante es si ha cambiado o no la probabilidad de cara de la moneda. De lo cual, y volviendo al caso de la siniestralidad, ya me ocupé en su día.
Imagínate que quieres estabilizar la varianza (¡para qué!) de una distribución de Poisson. Los libros viejunos te dirán que saques la raíz cuadrada de tus valores.
Si en lugar de mirar en libros viejunos prestas atención a tus propios ojos, harás algo parecido a:
lambdas <- -10:10
lambdas <- 2^lambdas
res <- sapply(lambdas,
function(lambda) sd(sqrt(rpois(1e5, lambda))))
para obtener
y averiguar dónde funciona y dónde no.
Si usas la transformación $latex f(x) = x^{2/3}$, como recomiendan en cierto artículo que no viene a cuento identificar, harás
Primero, una simulación:
n <- 100
delta <- 0.2
n.iter <- 10000
p_valores <- function(n, delta){
tmp <- replicate(n.iter, {
x <- rnorm(n)
y <- rnorm(n, mean = delta)
t.test(x, y)$p.value
})
res <- tmp[tmp < 0.05]
hist(res, freq = FALSE, xlab = "p value", ylab = "", col = "gray", main = "histograma de p-valores publicables")
res
}
null_effect_p_values <- p_valores(n, 0)
some_effect_p_values <- p_valores(n, delta)
Lo que simula son n.iter
experimentos en los que se comparan n
valores N(0,1) con otros n
valores N(delta
, 1) y se extrae el correspondiente p-valor. Luego se grafican los publicables (<0.05).
El otro tropezamos 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, por que la documentación reza:
x$name is equivalent to x[[“name”, exact = FALSE]]
Y se pueden constrastar:
a[["a", exact = FALSE]]
a[["a", exact = TRUE]]
Comentarios:
Cuando tienes una serie temporal al uso (sin entrar a definir qué es eso), uno puede aplicar descomposiciones tmabién al uso, como stl
, para extraer tendencia y estacionalidad, de la forma
como en esta entrada previa.
Lluvia.
La serie de la lluvia es otra cosa. Uno ve si llueve o no llueve (típicamente no). Lo que uno no ve es la probabilidad, que varía a lo largo del año, de que llueva. Pasa lo mismo con monedas (uno ve caras o cruces, no la probabilidad de cara), clientes que compran (uno ve si compra o no, no la probabilidad de compra), etc. Pero la probabilidad existe y en estimarla consiste frecuentemente el trabajo de algunos.
Me escriben pidiendo consejo sobre cómo leer datos contenidos en (una serie larga de) ficheros en formatos .dbf
, .xlsx
(con un formato extraño) y .pdf
.
.dbf
No tengo ni curiosidad por averiguar de dónde proceden. Simplemente,
library(foreign)
res <-read.dbf("R0010.DBF")
funciona de maravilla.
.xlsx
Estos sí que sé de dónde vienen (y me guardo la opinión). El problema aquí no era leer directamente tablas contenidas en hojas sino ir extrayendo celdas y rangos de hojas. Así que:
Se ve que hay arqueólogos bayesianos. Un problema con el que se encuentran es que tropiezan con cacharros antiguos y quieren estimar su antigüedad.
Así que prueban distintos métodos (¿químicos?), cada uno de los cuales con su precisión, y acaban recopilando una serie de estimaciones y errores. Obviamente, tienen que combinarlas de alguna manera.
El modelo más simple es
$$ M_i \sim N(\mu, \sigma_i)$$
donde $latex \mu$ es la antigüedad (desconocida) del artefacto y los $latex \sigma_i$ son las varianzas distintas de los distintos métodos de medida, que arrojan las estimaciones $latex M_i$.
Envalentonado por el comentario de Iñaki Úcar a mi entrada del otro día, que me remitía a este artículo, decidí rizar el rizo y crear intervalos de confianza no ya discontinuos sino con otra propiedad topológica imposible: homeomorfos con un toro.
Y aquí está:
El modelo, el código y demás,
library(rstan)
library(ggplot2)
n <- 100
a1 <- 1
a2 <- 1
sigma <- 0.4
datos <- data.frame(x1 = rnorm(n, 2, 0.1),
x2 = rnorm(n, 2, 0.1))
datos$y <- a1^datos$x1 + a2^datos$x2 + rnorm(n, 0, sigma)
codigo <- "
data {
int<lower=1> N;
real y[N];
real x1[N];
real x2[N];
}
parameters {
real<lower=-3, upper="3"> a1;
real<lower=-3, upper="3"> a2;
real<lower=0, upper="3"> sigma;
}
model {
for (n in 1:N)
y[n] ~ normal(fabs(a1)^x1[n] +
fabs(a2)^x2[n], sigma);
}"
fit <- stan(model_code = codigo,
data = list(N = length(datos$y), y = datos$y,
x1 = datos$x1, x2 = datos$x2),
iter=40000, warmup=2000,
chains=1, thin=10)
res <- as.data.frame(fit)
ggplot(res, aes(x = a1, y = a2)) + geom_point(alpha = 0.1)
De nuevo, no son intervalos propiamente dichos, lo convengo. Pero son configuraciones más fieles al espíritu de lo que un intervalo de confianza es y representa que su(s) letra(s) I N T E R V A L O.
curve(-sqrt(x^2 + 1), -5, 5)
pinta una rama de hipérbola,
que, una vez exponenciada, i.e.,
curve(exp(-sqrt(x^2 + 1)), -5, 5)
da
Es decir, una curva algo menos esbelta que la normal pero que bien podemos dividir por su integral para obtener la llamada distribución hiperbólica.
Tres notas sobre ella:
ghyp
, motivado por aplicaciones financieras, como siempre. Esa gente es adicta a distribuciones con colas gruesas. Aunque para lo que les valen luego…Continúo con esto que concluí con una discusión que me negué a resolver sobre la geometría de los errores.
Que es la manera de entender que los problemas directos e inversos no son exactamente el mismo. Digamos que no es una medida invariante frente a reflexiones del plano (que es lo que hacemos realmente al considerar el modelo inverso).
¿Pero y si medimos la distancia (ortogonal) entre los puntos $latex (x,y)$ y la curva $latex y = f(x)$ (o, equivalentemente, $latex x = f^{-1}(x)$)? Entonces daría (o debería dar) lo mismo.
Inspirado por esto he tratado de contrastar una hipótesis en otro contexto.
Las cosas, o se hacen bien, o no se hacen. Como mi análisis se ha complicado con casos y casitos particulares, aunque siga pensándo cierta (en caso de tener que apostar, como priori, claro) la hipótesis de partida, abandono su búsqueda.
Como subproducto, esto:
library(xml2)
library(stringr)
library(plyr)
library(lubridate)
periodos <- expand.grid(anno = 2010:2017, mes = 1:12)
periodos$ind <- periodos$anno * 100 + periodos$mes
periodos <- periodos[periodos$ind < 201711,]
periodos <- paste(periodos$anno,
str_pad(periodos$mes, 2, pad = "0"), sep = "_")
raw <- lapply(periodos, function(x){
url <- paste0("http://www.eldiario.es/sitemap_contents_", x, ".xml")
print(url)
as_list(read_xml(url))
})
#df <- lapply(raw, function(y)
ldply(y, function(x) as.data.frame(t(unlist(x)))))
res <- lapply(raw, unlist)
res <- lapply(res, function(x) t(matrix(x, 3, length(x) / 3)))
res <- data.frame(url = res[,1],
time = res[,2], stringsAsFactors = FALSE)
res$time <- gsub("\\+.*", "", res$time)
res$time <- strptime(res$time,
"%Y-%m-%dT%H:%M:%S")
res$titular <- gsub("_0_[0-9]*.html", "", res$url)
res$titular <- gsub(".*/", "", res$titular)
res$titular <- tolower(res$titular)
res$year <- year(res$time)
res$month <- month(res$time)
Igual le sirve a alguien para analizar palabras clave en titulares de ese u otro medio, su evolución por mes, etc.