[ GIT ] Inconsistencias en archivos remotos y locales

Cuando utilizamos git pull origin master internamente se ejecutan dos comandos: `git fetch` y git merge.

El primer comando git fetch origin master descarga el contenido de la rama (branch) master del repositorio origin Mientras, el comando git merge junta los archivos descargados con la rama master local. Es muy frequente que tengamos algunos archivos differentes a los del repositorio remoto y a la hora de hacer el mergese presenten inconsistencias entre el repositorio remoto y el local.

La forma más común de corregir esto es editando el archivo con problemas (usar git statussobre la raíz del repositorio) y seleccionar la versión que necesitemos, es decir, entre la version remota y la local. Git automaticamente añade las dos versiones en el archivo aludido concatenado las líneas de texto difentes entre las dos versiones. Estas diferencias son fácilmente visibles por que git añade adicionalmente las líneas >>>>[hash commit remoto] para las diferencias provenientes del repositorio remoto, y >>>HEAD para la version local. Ambas versiones están separadas por los símbolos =======. Recuerda, estas modificaciones son automáticamente añadidas en el archivo que presenta el problema.

Una vez que hemos borrado la versión que no queremos proseguimos a salvar el archivo, añadirlo al Stage de git (con git add [archivo problematico]) y luego hacemos un commit (git commit -m "alguna mensaje").

Arreglar inconsitencias en archivos grandes

Algunas veces editar manualmente cada archivo problemático puede ser engorroso o simplemente ya sabemos que alguna versión es mejor que la otra. Por ejemplo la versión local (nuestra versión) puede estar más actualizada o la versión remota (la del ellos) puede ser más estable.

En versiones git > 1.6.1 podemos utilizar la opción --ours (nuestra versión) o --theirs (la de ellos) para seleccionar si queremos mantener la versión local o la versión remota (respectivamente). Esta opción sólo es válida para el comando git checkout [archivo problemático] . De esta manera podemos hacer:

git checkout --ours [archivo problemático]

Para quedarnos con nuestra versión.

git checkout --theirs [archivo problemático]

Para quedarnos con la versión remota.

Filtrar una mega lista de objetos

Sabemos que filtrar una lista en Python puede hacerse con la función filter, que recibe una función booleana y un iterable, por ejemplo una lista.

La historia es esta. Tengo una lista de 455, 864 objetos Occurrence (llamada omega_tree.occurrences) , y quiero filtrar de aquí (remover) 16,380 (de una lista llamada ocs_of_interest). Originalmente pensé en simplemente hacer un filter:

ocs_complements = filter(lambda occurrence : occurrence not in ocs_of_interest , omega_tree.occurrences)

Estaba cansado y decidí dejar la compu corriendo. Cuando regresé a trabajar (12 horas después) el proceso seguía corriendo…

Pensé que tal vez se estaba lo que ocasionaba la demora era el método __hash__ y __eq__ que se utiliza para decidir si un elemento es igual al otro por lo que extraje solo el índice (un mapeo de los objectos Occurrence a Int). Esto hizo, efectivamente, más eficiente el filtrado pero igual, haciendo unas estimaciones a bote pronto me dijeron que posiblemente tardaría unas 10 horas… Rubish!

Me puse a buscar y encontré que la clase Set no solo es útil para remover elementos repetidos dentro de listas pero también hace muy eficiente la busqueda y, en mi caso, filtrado de objectos grandes.

Hice un cast (conversión) a lista para obtener un set. Los resultados fueron sorprendentes!!

%time ofi = set(map(lambda o : o.pk, ocs_of_interest))
%time oo = set(map(lambda o : o.pk ,omega_tree.occurrences))
%time ocs_complements = filter(lambda occurrence : occurrence not in ofi , oo)

CPU times: user 116 ms, sys: 0 ns, total: 116 ms
Wall time: 114 ms
CPU times: user 3.24 s, sys: 8 ms, total: 3.25 s
Wall time: 3.26 s
CPU times: user 136 ms, sys: 0 ns, total: 136 ms
Wall time: 133 ms

Conclusión

Para filtrar una lista grande de objetos conviene convertir la lista a conjunto (Set). El aumento de rendimiento es increiblemente grande!

Bacalao a la Vizcaína Mexicana

Ingredientes

  • 1 Kg de Bacalao
  • 1.3 Kg de Jitomate
  • 400g de cebolla
  • 200g de ajo
  • 1 manojo de perejil
  • 2 pimientos pelados (rojos) (puede ser lata)
  • 200g de aceitunas sin hueso
  • 150g de alcaparras
  • 1/2 taza de almendras
  • 2 tazas de papa cortada o chiquita
  • 1/2 taza aceite de oliva
  • 3 Rebanadas de pan
  • chiles gueros

Elaboración

Preprocesamiento

Cocer el bacalo, si es fresco. Hacer un caldito tarda poco. Una vez frío se desmenuza en lajitas.

Pelar el jitomate con el método del chef. Cortas los jitomates separas el endospermo (parte gelatinosa) con semillas y se pica el jitomate sin semillas. Las cáscaras y el endospermo se muele y se cuela. A esto se le llama purecito.

Se echan en una olla con agua hirviendo por un minuto y luego se sacan y echan al agua fria. Asi se pelan muy rápido.

El método del Chef

Se pica toda la cebolla en pequeños cubitos.

Se asan los pimientos para pelarlos con el método del sudado de chiles (trapo húmedo). Se parten en rajas.

Las aceitunas y alcaparras se ponen enteras, sin la salmuera.

Se pica o raya el ajo. El perejil también se pic finamente.

Las almendras se pelan con agua caliente y así se pelan fácilmente. Apachurrándolas suavemente. Se cortan en rebanaditas.

Dependiendo del tamaño de las papas se pueden cocer previamente si son grandes y ponerlas en el guisado en el último hervor.

Procedimiento del guisado

En una olla grande pones una parte de aceite, un poco, y se pone a freir unos dos dientes de ajo enteros con las rebanas de pan. Esto para que espese la salsa y quede rico. Retiras el pan dorado, sin dejar quemar junto con los ajos.

Una vez separado el pan y el ajo se muelen con un poco de purecito para formar una pastita.

Poner la cebolla y los ajos a freír. Una vez ya están sofritos se añade el jitomate, las papas y el perejil y se deja sazonar. Se le añade el purecito y la pastita de panajo. Si el jitomate está agrio se le puede pone una pizaca de azúcar.

En caso de usar bacalao seco (previo tratamiento) se añade en ese momento y se deja hervir al menos una hora. En caso de ser fresco no se necesita esto y se añade después.

Se añaden las aceitunas, alcaparras.

Se añaden los pimientos.

Se deja cocinar a fuego bajo hasta que el aceite suba y “haga ojos”. Se le pone sal al gusto y se le va añadiendo el caldito de bacalao mientras se esta cocinando la salsa.

Los “ojitos” del bacalao

En caso de usar bacalao fresco, se ponen las lajitas se pone en ese momento.

Se sirve con pan y con los chiles güeros.

Regresión logística jerarquizada con STAN

Estoy sorprendido por la capacidad y flexibilidad para expresar modelos estadísticos complejos con STAN. Como sabrán, STAN es un lenguage declarativo de programación probabilístico. Los modelos estadísticos son descritos con una sintaxis sencilla para especificar de una forma muy similar a lo que hacemos en el pizarrón o en papel. STAN está basado en principios bayesianos y utiliza varios métodos para muestrear distribuciones posteriores, entre los más conocidos están Hamiltonian Monte Carlo, Non U Turn y Metrópolis-Hastings (no voy a meterme a detalle en esto ahora, en internet hay montón de referencias al respecto).

En este post veremos como definir un modelo logistico jerárquico. Supongamos que para toda observación binaria \(y_i \in \{0,1\} \) existe un nivel associado \(j_i \in \{1,2,…,J\}\) y un vector de covariables (predictores) \(x_i \in \mathbb{R}^K\). Supondremos pues que las observaciones son realizaciones de un proceso bernoulli independendiente cuando se condiciona con un proceso normal jerarquizado. Esto es:

\([Y | S] \sim Bernoulli(S)\)

Ahora, \(S\) puede ser descrita de la siguiente forma:

\(S_{i,j} = \beta^t_j x_i + \epsilon\)

Y se lee de la siguiente forma. La variable S en la observación i del nivel j es igual a \(\beta^t_j x_{i} + \epsilon \). Es decir, el vector \(\beta\) son los coeficientes associados a la respuesta \(S_{i}\) en el nivel j.

En STAN esto es equivalente al siguiente código:

hierarquical_log_model = u"""
data {
  int<lower=0> N; // num obs. 
  int<lower=0> J; // number of levels
  int<lower=1> K;                // num covariates
  matrix[N, K] x;                // design matrix
  int<lower=1,upper=J> level[N];  // type of level (spec)
  int<lower=0,upper=1> y[N];              // observations, in this case is binary.
  
} 
parameters {
  real mu[K];
  vector[K] beta[J];
  real<lower=0,upper=100> sigma; // same sigma

}

model {
    for (k in 1:K) {
        mu[k] ~ normal(0,100);
        for (j in 1:J)
            beta[j,k] ~ normal(mu[k], sigma);
    }
    for (i in 1:N)
        y[i] ~ bernoulli_logit(x[i] * beta[level[i]]);
  
}"""

Para correr el modelo en Python usando PyStan hacer esto.

varying_intercept_model = pystan.StanModel(model_code=hierarquical_log_model)
multilevel_linear_data = {'N': X.shape[0],
                          'J': 2,
                          'K': X.shape[1],
                          'level': data.codes.values, # niveles
                          'x' : X.values,
                          'y': data.obs.values}
%time fit = varying_intercept_model.sampling(data=multilevel_linear_data, iter=1000,chains=1)
sample = fit.extract(permuted=True)

En este caso mis datos están definidos en un Pandas Dataframe llamado X, separado de las observaciones. Para eso use patsy. La muestra de la distribución posterior estará guardada en el objeto ‘sample’

Envolver líneas (text wrap) en VIM

Text wrap es el proceso de insertar saltos de línea automágicamente para poder visualizar líneas de texto mas grandes que la ventana del editor de texto (IDE).

Muchos IDEs hacen esto y VIM no es la excepción.

Para activarlo usar:


:set tw='n'

Donde ‘n’ es el número de caracteres por línea.

Para detener el proceso de wrap (envolver) hay que usar ‘n’=0

Modificar margen antes de aplicar wrap

Para modificar este valor usar:

:set wm=k

Donde ‘k’ es el numero de caracteres por tolerar antes de aplicar el wrap (cuando se haya sobrepasado el límite tw)

Soft wrap

Se no se quiere insertar símbolos EOL y únicamente se quiere visualizar saltos de línea úsese:

:set wrap linebreak nolist

Mas información

[N] VIM Shortcuts

My lista de los atajos (shortcuts) más usados en [N]VIM

Substituir texto entre dos marcadores

Ya sabemos que con la teclas [m] + [a-z] creamos un marcador dentro del archivo.

Podemos entonces substituir texto entre cualesquiera par de marcadores utilizando el siguiente comando (en modo Normal).

Supongamos pues que queremos cambiar la palabra ‘Político Priísta’ por ‘Rata’. Dentro del texto:

a

“El poder no lo debe tener y nunca debió haber regresado a Los Pinos ese poder del presidente con el PRI”, manifestó el político priista, quien el domingo a la noche no acompañó a José Antonio Meade Kuribreña en su noche triste..

b


El comando sería el siguiente:

:’a , ‘bs/político priista/rata/gc

Las opciones g y c significan: global (cambiará todas las occurrencias encontradas en cada línea) y confirmation (preguntará por confirmación para sustituir).

Hay más información aquí: https://vim.fandom.com/wiki/Search_and_replace


¿ Cómo crear paquetes de R ?

Objetivos

Queremos hacer un paquete (i.e. un conjunto de funciones, datos y documentación de R). El paquete debe ser accesible desde internet de la manera más eficiente posible. Se deben seguir las mejores prácticas de la comunidad, incluir los datos a utilizar, ejemplos , etc

Crear un repositorio Git

Lo primero que tenemos que hacer es crear un repositorio GIT. Hay muchos tutoriales ahí afuera para hacer repositorios. Usa el google.

Supongamos pues, que tenemos uno ya hecho. En mi caso, hice un fork de CARBayes (Duncan Lee) y lo puse en mi repositorio público en Github (https://github.com/molgor/CARBayeSDM.git )

Fijensé como esta la estructura de los archivos.

Paquetes necesarios

install.packages("devtools")
library("devtools")
install.packages("roxygen2")
library("roxygen2")

 

Devtools permite instalar paquetes desde repositorios GIT además de otras utilidades para desarrolladores. Roxygen es una librería crear documentación en R. Su nombre viene de la popular applicación Doxygen para crear documentación.

Inicializar la estructura

Podemos utilizar la función ‘create_package(Nombre_de_paquete) ‘ para crear una estructura de directorios.

setwd('ruta del repositorio')
create_package('mi_paquete')

La estructura quedará de la siguiente manera :

  • R (Carpeta donde se guardará el código de R)
  • man (Donde se guardará la documentación)
  • DESCRIPTION (archivo Readme que contiene la descripción del paquete)
  • NAMESPACE (configuración de las funciones definidas por el paquete)

 

Escribir función con documentación

Vamos a escribir las funciones dentro de la carpeta R. Aquí definiremos las funciones pero primero pondremos la documentación (descripción de cada función al comienzo del archivo). Ve el siguiente ejemplo. El archivo se llama: *MyTestingFunction.R* [ Disculpa por escribirla en inglés, ya quedará en ustedes traducirla] .

#' An example for writing a function in R using Roxygen (e.g. a variant of Doxygen for
#' R) 
#' Well, this function is for writing stuff, I suppose that I need to write here the
#' pourpose of the function.
#' @param something Something to put
#' @keywords Tests, examples, many
#' @export
#' @examples
#' test_function()

test_function  <- function(something=TRUE) {
  if(something==TRUE) {
   c = 'Something is True'
  return(c)
  }
  else {
    c = 'Something is different from TRUE'
    return(c)
  }
}

Compilar documentación e instalar

Para compilar la documentación basta con ejecutar:

document()

 

Para instalar todo:

setwd("..")
install("mi_paquete")

Usando repositorio en Github

Si se opta por esta opción se puede instalar directamente usando la función:

install_github('mi_paquete','usuario_de_github')

Listo! A desarrollar

Ahora podemos desarrollar paquetes de R, subirlos a github y compartirlos con todos nuestros colegas.

Colabora y no seas culer@!
Este post está basado en el ejemplo de Hillary Parker .

Solucionar: IO Error ‘[Errno 28] No space left on device’

Este error es frecuente al utilizar librerías de Python de multiprocesamiento ‘joblib’ con una cantidad considerable de datos.

Diagnostico

El problema es que la memoria compartida ‘/dev/shm’(usualmente menor que la memoria RAM) se satura.

Para corregirlo tendremos que cambiar la variable de entorno: JOBLIB_TEMP_FOLDER a un directorio que con mayor capacidad. (e.g. /tmp)

Esto puede hacerse directamente en iPython o Jupyter con:

%env JOBLIB_TEMP_FOLDER=/tmp

O agregandola en el shell con:

$ export JOBLIB_TEMP_FOLDER=/tmp

[Tutorial R] Modelos CAR generalizados

En este post veremos como ajustar *Conditional Autoregressive Models* (Una variante de Gaussian Markov Random Fields) a un conjunto de datos generados por Biospytial.

Para cargar los datos vaya a https://ecomorphisms.holobio.me/2019/01/28/tutorial-para-analisis-de-datos-espaciales-en-r/ 

Requisitos

Instalar paquete CarBayes

install.packages(‘CARBayes’)

The conditional autologistic model (Besag, et. al 1991) has the following specification (Lee, 2013).

$$k \in {1…K}$$ Neighbours

$$ Y_k \sim Binomial(n_k,\theta_k) $$

$$ ln\left(\frac{\theta_k}{1-\theta_k}\right)= x_k^t \beta + O_k + \psi_k$$

$$\beta \sim N(\mu_\beta,\Sigma_\beta)$$

$$ \psi_k = \phi_k + \theta_k $$

$$ \phi_k | \phi_{-k}, \mathbb{W},\tau^2 \sim N \left( \frac{\sum_{i=1}^{K} w_{ki} \phi_i}{\sum_{i=1}^{K}w_{ki}}, \frac{\tau^2}{\sum_{i=1}^{K}w_{ki}}\right) $$

$$\theta_k \sim N\left(0, \sigma^2\right)$$

$$\tau^2, \sigma^2 \sim^{iid} Inv.Gamma(a,b) $$

Referencias



Cargar datos en R

… y ajustar un modelo GLM

Introducción

Este post quiere ser un pequeño acordeon (chuleta) de ciertas funciones y paquetes en R para hacer análisis espaciales.
Si, he aceptado que hay un montón de cosas que valen la pena en R y este es mi intento de volverme a acercar a ese lenguaje que sigo considerado obscuro y sucio. Sin embargo, a la comunidad de estadística le gusta. Supongo que por razones históricas y la típica ley de potencia de Winners take all… Yo

Supuestos

  • Datos extraidos de Biospytial y guardados en CSV en el backend de Redis.
    • > (Actualizado. el objeto en redis es un pickle de un DataFrame de Pandas. No he encontrado forma trivial de portar estos objetos en R. Se utiliza entonces un formato CSV (estandar) guardado con antelación)
  • Command-line. No hay interfáz gráfica

Preparación

  • Seleccionar un repositorio CRAN (alguno de los dos)
    chooseCRANmirror(graphics=FALSE)
    options(repos='http://cran.rstudio.com/')
  • Cargar driver de Redis
    • library('rredis')
  • Conectar a BD redis
  • redisConnect(host='redis',password='biospytial.')
     
  • Read data from CSV
    TDF = read.csv("/outputs/training_data_sample_puebla_p2_abies_pinophyta.csv")
    PDF = read.csv('/outputs/presence_only_models/predictors/dataset100x100-puebla-p2/0-pred.csv')
     

Definir el modelo

$$ Y(x) = Dist.Road + Pop.denst + vegtype$$ Se procederá a ajustar un modelo GLM con supuestos de independencia en los residuales (i.e. estandard GLM). formula = ‘Pinophyta ~ Dist.to.road_m + Population_m + tipos’ mod_sig = glm(formula, data=TDF, family=binomial()) summary(mod_sig) confint(mod_sig)