This is how Airbnb is really being used in Brussels.

Airbnb claims to be part of the «sharing economy» and disrupting the hotel industry. However, data shows that the majority of Airbnb listings in most cities are entire homes, many of which are rented all year round – disrupting housing and communities.

In this article, we will be exploring how AirBnb is being used at my home city: Brussels, Belgium.

Room Type

Airbnb hosts can list entire homes/apartments, private or shared rooms.

Depending on the room type, availability, and activity, an airbnb listing could be more like a hotel, disruptive for neighbours, taking away housing, and illegal.

I first wanted to have an idea on the distribution of room types in the city.

Room type distribution for AirBnB apartments in Brussels, BE

No surprise here. Most listings are for entire homes or apartments, which is what most people look for when on a vacation. Now, let’s take a look at the average price for rooms on each category:

Avg price for each type of AirBnB room in Brussels, BE

Hotel rooms on that price are not really attractive. Interesting is to see that the avg price for a shared room is not much more cheap than the price for a private room.


Airbnb guests may leave a review after their stay, and these can be used as an indicator of airbnb activity. This is how most metrics are estimated.

The minimum stay, price and number of reviews have been used to estimate the occupancy rate, the number of nights per year and the income per month for each listing. Everything is in the companion dataset.

AirBnB activity in Brussels from Jan 1, 2010 to Apr 1, 2020
AirBnB activity in Brussels from Jan 1, 2019 to Apr 1, 2020
Estimated Nights per Listing

You can definitely see a steep decrease towards the end there!. Covid-19 effects!

Some interesting questions worth answering are:

  • Do the number of nights booked per year make it impossible for a listing to be used for residential housing?
  • And what is renting to a tourist full-time rather than a resident doing to our neighbourhoods and cities?
  • How does the income from Airbnb compare to a long-term lease?

I will answer these on a new post.


An Airbnb host can setup a calendar for their listing so that it is only available for a few days or weeks a year.

Other listings are available all year round (except for when it is already booked).

Entire homes or apartments highly available year-round for tourists, probably don’t have the owner present, could be illegal, and more importantly, are displacing residents.

Let’s see the availability distribution from 1 to 365 days a year :

Year availability distribution.

Now, let’s do a pie chart to check the relationship between low (less than 90 nights/year) and high (more than 90 nights/year) availability:

High vs Low Availability

Listings Per Host

Some Airbnb hosts have multiple listings. A host may list separate rooms in the same apartment, or multiple apartments or homes available in their entirety.

Hosts with multiple listings are more likely to be running a business, are unlikely to be living in the property, and in violation of most short term rental laws designed to protect residential

Number of listings per unique host registered on AirBnb Brussels.

As we can see, AirBnb is not necessarily being used as it is originally intended. If you want to know more on the concerns related to these practices, read here, here and here.

Get the data

All data is available on

The python notebook is on

Below is the PDF printout of the Jupyter Notebook.

Useful AWS CLI Scripts that use JQ

Ever found yourself in the need to quickly print details or execute commands on multiple of the same type of AWS resource? Like, get the size of all your s3 buckets, all list/update all tags on your EC2 machines? AWS CLI is more than enough!

The following are a set of useful AWS CLI scripts that make use of either command querying or parse the json output using JQ to for loop a list of resources and execute modify commands or get additional details on them.

AWS CLI diagram
AWS CLI is a unified tool to manage your AWS services

All these assume you have a local install of both AWS CLI and JQ, and you have CLI configured with your account and region.

Code Completion for AWS CLI on your bash_profile

First, a useful script to allow aws cli code completion on your bash profile. Useful for when you don’t remember all the commands (Which are a lot)

List all EMR Clusters along with the associated EC2 Instance Ids

This one will list all EMR Clusters along with the associated EC2 Instance Ids.
It will print the result in the format: # "cluster_id | [$ec2_instance-id]... "

List all AMIs along with any associated instances

At work, we recently had the need to list all our unused AMI’s, making sure they are not being used by any instance or running resource. This is how you can get such a list

Add Tags to a Kinesis Stream

Adding tags is a useful feature for organizing your resources. At my work, we use it for cost allocation across teams. This is a simple way to do so. Notice you can customize this one to work for any kind of resource that allow tagging.

Get S3 Buckets Tags

Tags, or any details/Information, really. Just change or add the appropriate field on the query, and have it printed.

If you are curious, there’s a lot more Gists on my Github profile.

Obtuve mi invitacion al reto de Google. Y planeo terminarlo!

Ayer, cuando buscaba una información básica sobre Python para poder enviarle un enlace a mi primo, que está viendo asignaturas de programación, Google hizo una animación que no había visto:

Google Foo Bar es el proceso secreto de reclutamiento de Google incrustado en su motor de búsqueda. Hay 5 niveles, cada uno con un número diferente de desafíos que siguen una historia.

Mi interfaz de

Aquí, les estaré compartiendo mi experiencia y algunos tips:

Nivel 1

Me dieron 24 horas para completar este primer problema, y fue bastante simple. Era básicamente algo que verías en cualquier curso de ciencias de la computación de nivel universitario, y me tomó poco tiempo terminarlo.


  • Sigue las mejores prácticas.
  • Usa buenos nombres de variables.
  • Agrega tus propios casos de prueba.
  • No temas hacer uso de un editor externo.
  • Valida las entradas y los casos especiales.
Reto 1

Autoscaling for AWS EMR Clusters

Allow EMR Clusters to Auto Scale based on cluster usage, allowing our applications to be more reactive and cost-efficient.

Estimated Impact

  • Better performance and reaction to load spikes.
  • Cost savings on EMR resource usage.


  • Measurement can be done by comparing the overall number of deployed instances before/after Autoscaling is enabled everywhere possible.
  • Also, it might be possible that by enabling AutoScaling, some EMR Instance Types may be changed to less powerful ones.

What we know so far

About EMR Auto-scaling

  • EMR allows auto-scaling only on TASK node types. You can set any instance type, which is going to be used for new servers.
  • You can set the minimum and maximum instances there can be. (I have gone with 0 and 6 respectively)
  • You can set the thresholds for scaling out and in on instance count. Available metrics are the same as CloudWatch.
  • You need to specify an Autoscaling role. There’s a default AWS creates for you: `EMR_AutoScaling_DefaultRole`.
  • All this can be configured via CloudFormation using the InstanceGroupConfig type.
  • There is an issue where a cluster/stack with this configuration will fail to delete the regular way. More info HERE.
"FeedingAutoScale": {
       "Type" : "AWS::EMR::InstanceGroupConfig",
       "Properties" : {
         "AutoScalingPolicy" : {
           "Constraints": {
             "MaxCapacity": {
               "Ref": "AutoScalingInstanceMax"
             "MinCapacity": {
               "Ref": "AutoScalingInstanceMin"
           "Rules": [
               "Name": "Scale-out",
               "Description": "Scale-out policy",
               "Action": {
                 "SimpleScalingPolicyConfiguration": {
                   "AdjustmentType": "CHANGE_IN_CAPACITY",
                   "ScalingAdjustment": 1,
                   "CoolDown": 300
               "Trigger": {
                 "CloudWatchAlarmDefinition": {
                   "Dimensions": [
                       "Key": "JobFlowId",
                       "Value": {
                         "Ref": "FeedingCluster"
                   "EvaluationPeriods": 1,
                   "Namespace": "AWS/ElasticMapReduce",
                   "Period": 300,
                   "ComparisonOperator": "LESS_THAN",
                   "Statistic": "AVERAGE",
                   "Threshold": {
                     "Ref": "AutoScalingScaleOutYarnMAP"
                   "Unit": "PERCENT",
                   "MetricName": "YARNMemoryAvailablePercentage"
               "Name": "Scale-in",
               "Description": "Scale-in policy",
               "Action": {
                 "SimpleScalingPolicyConfiguration": {
                   "AdjustmentType": "CHANGE_IN_CAPACITY",
                   "ScalingAdjustment": -1,
                   "CoolDown": 300
               "Trigger": {
                 "CloudWatchAlarmDefinition": {
                   "Dimensions": [
                       "Key": "JobFlowId",
                       "Value": {
                         "Ref": "FeedingCluster"
                   "EvaluationPeriods": 1,
                   "Namespace": "AWS/ElasticMapReduce",
                   "Period": 300,
                   "ComparisonOperator": "GREATER_THAN",
                   "Statistic": "AVERAGE",
                   "Threshold": {
                     "Ref": "AutoScalingScaleInYarnMAP"
                   "Unit": "PERCENT",
                   "MetricName": "YARNMemoryAvailablePercentage"
         "Name": "AutoScaling TASK",
         "InstanceCount": {
           "Ref": "AutoScalingInstanceCount"
         "InstanceRole" : "TASK",
         "InstanceType": {
           "Ref": "AutoScalingInstanceType"
         "JobFlowId": {
           "Ref": "FeedingCluster"

About Dynamic Allocation

For AutoScaling to work correctly, no fixed set of executors need to be configured. Instead, Spark needs to be able to allocate resources dynamically. This concept has been around for a while. It uses previous job metrics to calculate a dynamic load. There exists two relevant settings for this:

  • `spark.dynamicAllocation.enabled`  – Since Spark 1.5
  • `spark.streaming.dynamicAllocation.enabled`  – Since Spark 2.0.0

As our Feeding application is a Spark streaming one, we need the latter. However, EMR automatically sets `spark.dynamicAllocation.enabled` to true behind doors in an attempt to optimize apps for you. As these two settings are incompatible (They can’t be both enabled), we need to explicitly disable it. More info on Spark settings EMR changes automatically can be found HERE.

Other spark configs that don’t play well with StreamingDynamicAllocation are:

  • `spark.executor.cores`
  • `spark.executor.instances`

Those need to be left out.

On upgrading EMR (and Spark) versions

For Spark Streaming Dynamic Allocation, it is recommended to use Spark version > 2.0.1. Currently, our setup uses EMR release version 5.0.0, which comes with Spark 2.0.0. An EMR release upgrade is needed in order to use Dynamic Allocation and Auto-scaling working. I’ve decided to go straight for the most recent EMR release version, which as of February 2018 is EMR 5.11.1

To know more on EMR release versions, and see details, go HERE.

What changed on Spark?

Mainly, two things are different on Spark 2.2.1 in our scenario:

  • Spark stopped distributing Kinesis API’s because of licensing/legal issues. Jira HERE.
  • AWS deprecated a method we used on our streaming API to get the region based on the Kinesis endpoint. Javadoc HERE. Changes needed for SparkFeeding HERE.

To solve the first, we can use --packages org.apache.spark:spark-streaming-kinesis-asl_2.11:2.1.0 to add spark-streaming-kinesis-asl and its dependencies into the classpath automatically, rather than building the assembly jar by ourselves. However, for SBT to don’t fail on artifact building, it is required to use the %provided keyword for that library on `build.sbt`.

To solve the second issue, the `getRegion` method o the same class can be used. That one takes a string with the name of the region, which can be easily set on the spark config with the following CloudFormation property:

«»: {
«Ref»: «AWS::Region»

Getting YARN Logs on EMR

All this investigation was possible, by taking a look at the YARN error logs. If there is a need to take a look at the reason of a failed Spark Application.

Having trouble troubleshooting a failed Spark Application like Spark_Feeding? EMR will gather stderr and controller logs and upload them to S3, but most of the time the provided information will not be enough. So, here’s how you can get it:

  1. Go to the EMR cluster’s page in AWS
  2. In the summary page, note the Master’s public DNS.
  3. Fix the URL (i.e. ip-172-00-0-00.ec2.internal: … => …)
    1. Tip: There is an add-on for Chrome that fixes it for you!
  4. SSH as hadoop to that address, providing the team’s SearchInfra_Search credentials file.
  5. You can now issue YARN commands to list applications and get the complete logging

Example commands

  • Get active applications details: yarn application --list
  • Get failed applications details: yarn application --list -appStates FAILED
  • Get an application full logs: yarn logs --applicationId <applicationID>

Infrastructure as Code – AWS Redshift (Boto3)

The following is an example/template of Infrastructure as Code (IAC) for deploying an AWS Redshift cluster using Python and Boto3. Here’s the target architecture:

Target Redshift AWS Architecture

For this to work, you will need to create an AWS account and IAM user with appropriate permissions to Redshift and S3. After that, just input your own user secret and key into the attached notebook.

You can download the ipynb notebook. Or just check the Jupyter notebook below:

On the next post, we will discuss how to Extract, Transform and Load (ETL) data into this Redshift Database via parallel imports using S3.

Hadoop – Ejemplos de hadoop-mapreduce-examples.jar

Hadoop MapReduce Una de las formas tradicionales de asegurarnos que un ambiente de Hadoop recién instalado funciona correctamente, es ejecutando el siempre presente jar de ejemplos map-reduce incluido con toda instalación de hadoop. Hablamos del hadoop-mapreduce-examples.jar.


En este tutorial, haremos un ejercicio que consiste en encontrar todas las apariciones de una palabra usando una expresión regular. Para hacerlo, crearemos un directorio llamado input en nuestro directorio de inicio y copiaremos los archivos de configuración (los xml) de Hadoop para usar esos archivos como nuestros datos de entrada.

Nota: la tilde (~) es un atajo muy útil en Bash para no tener que escribir la ruta de nuestra carpeta de usuario.

mkdir ~/input
cp /usr/local/hadoop/etc/hadoop/*.xml ~/input

A continuación, podemos usar el siguiente comando para ejecutar el programa (jar) hadoop-mapreduce-examples, un archivo Java con varias opciones. Invocaremos grep, uno de los muchos ejemplos incluidos en hadoop-mapreduce-examples, seguido por el directorio de entrada inputy el directorio de salida grep_example. El programa MapReduce grep contará las coincidencias de una palabra literal o expresión regular. Finalmente, proporcionaremos una expresión regular para encontrar ocurrencias de la palabra principaldentro o al final de una oración declarativa. La expresión distingue entre mayúsculas y minúsculas, por lo que no encontraríamos la palabra si estuviera en mayúscula al comienzo de una oración:

/usr/local/hadoop/bin/hadoop jar /usr/local/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.0.1.jar grep ~/input ~/grep_example 'principal[.]*'

El comando consta de las siguientes partes:

  1. /usr/local/hadoop/bin/hadoop Es el directorio donde esta el ejecutable de hadoop en el sistema.
  2. jar Le indica a hadoop que deseamos ejecutar una aplicacion empaquetada de Java. (Jar)
  3. /usr/local/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.0.1.jar Es la ruta donde esta el Jar que deseamos ejecutar. Note que la versión del jar depende de la versión de hadoop instalada.
  4. grep Es un parámetro de los muchos que se le pueden pasar al Jar de ejemplos que trae Hadoop. grep sirve para encontrar y contar ocurrencias de strings haciendo uso de expresiones regulares. Para ver una lista de los ejemplos que trae, click aquí.
  5. ~/input El directorio de entrada. Es donde el programa va a buscar los archivos de entrada a la tarea de map-reduce. Aquí copiamos unos archivos de prueba en un comando anterior.
  6. ~/grep_example El directorio de salida. Es donde el programa va a escribir el resultado de la corrida de la aplicación. En este caso, la cantidad de veces que la palabra del parámetro siguiente, aparece en los archivos de entrada.
  7. ‘principal[.]*’ Es la expresión regular que deseamos buscar. Esta expresión regular en particular coincide con la palabra ‘principal’ y ‘principal.’ (con y sin punto al final). Si desean saber un poco mas de expresiones regulares, les recomiendo este sitio web.

Cuando la tarea finaliza, proporciona un resumen de lo que se ha procesado y los errores que ha encontrado, pero esto no contiene los resultados reales.

. . .
 File System Counters
 FILE: Number of bytes read=1247674
 FILE: Number of bytes written=2324248
 FILE: Number of read operations=0
 FILE: Number of large read operations=0
 FILE: Number of write operations=0
 Map-Reduce Framework
 Map input records=2
 Map output records=2
 Map output bytes=37
 Map output materialized bytes=47
 Input split bytes=114
 Combine input records=0
 Combine output records=0
 Reduce input groups=2
 Reduce shuffle bytes=47
 Reduce input records=2
 Reduce output records=2
 Spilled Records=4
 Shuffled Maps =1
 Failed Shuffles=0
 Merged Map outputs=1
 GC time elapsed (ms)=61
 Total committed heap usage (bytes)=263520256
 Shuffle Errors
 File Input Format Counters
 Bytes Read=151
 File Output Format Counters
 Bytes Written=37

Nota: Si el directorio de salida ya existe, el programa fallará, y en lugar de ver el resumen, la salida se verá algo así como:

 . . .
 at java.lang.reflect.Method.invoke(
 at org.apache.hadoop.util.RunJar.main(

Los resultados se almacenan en el directorio de salida (~/grep_example/) y se pueden verificar ejecutando caten el directorio de salida:

cat ~/grep_example/*
 6 principal
 1 principal.

La tarea MapReduce encontró una aparición de la palabra principal seguida de un punto y seis apariciones en las que no estaba el punto. La ejecución del programa de ejemplo ha verificado que nuestra instalación autónoma (standalone, un solo servidor) funciona correctamente y que los usuarios no privilegiados del sistema pueden ejecutar Hadoop para su exploración o depuración.

Otros Ejemplos de Hadoop MapReduce

Vale la pena probar otros ejemplos contenidos en el jar, como por ejemplo:

  • Terasort: Se usa normalmente para hacer Benchmarking en clusters de hadoop.
  • PI: Calcula los decimales de PI usando MapReduce!

Branding Personal: Su importancia para los desarrolladores.

Todos tienen una historia. Aquí está la mía:

Hola, soy Leonel, y soy Ingeniero Senior de Software Venezolano en Panamá. Soy desarrollador Big Data, con inclinación a la ciencia de datos y experiencia en desarrollo móvil. Mi trabajo es tomar aquello que imaginas y hacerlo realidad, diseñar aquello que visionas, comunicar a aquellos que están alejados y resolver eso que te preocupa.

En mi vida, no solo soy Leonel, el ingeniero de software, o Leonel el padre, sino que también soy la marca ‘Leonel’, desarrollador Big Data que asiste a charlas, dicta cursos que puedes encontrar en Internet y tiene una introducción intencionalmente hecha a medida. Eso resume lo que hago.

La idea del personal branding de convertirte en una marca es bastante extraña. Algunas personas se rehúsan porque tiene la mala reputación de estar asociado con «vender un producto» o de que usted, como persona, es un producto o pertenece a una entidad. En esta época en la que todo el mundo odia a los fanfarrones más humildes, o no le gustan las tareas que se llevarán a cabo, es fácil ver por qué algunas personas no hacen nada con respecto a su marca personal.

Sin embargo, es imposible negar el poder de la marca. Desde lo que elegimos comprar hasta nuestras creencias y valores fundamentales, nuestras vidas están determinadas por la marca de alguien o de alguna compañía de alguna manera. Las decisiones que tomamos sobre las cosas, las ideas o las personas como resultado de las impresiones que tenemos se encuentran en el núcleo mismo de cómo los humanos interactúan con el mundo. Del mismo modo que usamos estas impresiones para guiar nuestra toma de decisiones, debemos ser conscientes de lo que nosotros, como desarrolladores y personas, ofrecemos al mundo y lo que forma nuestra propia marca.

Como desarrolladores o programadores, cuando vamos de un lugar a otro, generalmente no tenemos activos tangibles, como un artista tiene una cartera o un periodista tiene clips. El código, a menos que pertenezca a la comunidad Open Source (Código Abierto), es el dominio privado de los clientes o de la organización de la que forma parte y, como resultado, nos queda poco para diferenciarnos, además de un título y algunos puntos sobre un resumen. Esa falta de propiedad es lo que hace que la marca sea tan crucial, especialmente cuando es una de las únicas cosas que te diferencia.

Pero a medida que fui tomando experiencia como desarrollador de software, empecé a darme cuenta de lo importante que era desarrollar una marca personal. Esta práctica de definir mi marca personal no solo me ha permitido exhibir por completo el trabajo que hago como ingeniero, sino que también me ha ayudado a cultivar y descubrir quién quiero ser para el mundo.

La marca personal: Un cultivo a largo plazo.

Para mí, cultivar una marca es como hacer crecer una planta. Por defecto, una marca es como un par de raíces en el suelo, con algo de altura y hojas que han crecido hasta lo que es ahora. A diferencia de una planta real -que requiere que existan elementos establecidos de agua, luz solar y oxígeno-, una marca y la persona a la que está adherida no tienen ningún elemento establecido que necesite para tener éxito y no existen restricciones.

Puedes poner lo que quieras en tu marca y crecerá en lo que quieras que sea. A dónde va su marca, qué tan grande o pequeña es, qué tan rápido crece, eso depende de uno mismo. Incluso se puede cambiar de dirección a la mitad, lo cual es algo que no se puede decir sobre las plantas.

Ya sea que esté programando, trabajando o pensando en mi marca personal, me aseguro de seguir estos cuatro pasos: Definir, Crecer, Curar y Aprender.


La marca no se trata de lo que sientes o piensas acerca de ti, sino más bien de lo que otras personas sienten, piensan y dicen sobre ti. Esto fue bastante aterrador para mí al principio, pero rápidamente me di cuenta de que puede ser un alivio. La marca no se trata de ti, se trata de todos los demás y de cómo te perciben.

Para comenzar a definir su marca, hágase la pregunta «¿Por qué me conoce la gente?» Si tiene problemas con esto (lo cual hice), acérquese a sus colegas para obtener comentarios.


Después de recibir retroalimentación de sus compañeros y colegas, el siguiente paso en el proceso de desarrollo de la marca es la curaduría. La clave de este paso es comprender por completo lo que quiere que se sepa y evaluar si coincide con lo que la gente piensa de usted en su trabajo, proyectos o cualquier otra cosa y utilizar esta información como su modelo final. Otra forma de conceptualizar este paso es pensar: Si pudieras comenzar desde cero, ¿quién me gustaría ser?


Una vez que haya establecido quién va a ser su «futuro», el siguiente paso es hacer crecer la marca de esa persona. Una pregunta importante que debe hacer durante este paso es cómo va a pasar del presente al futuro.

Así es como lo hice: tomé las tres cosas por las que quería ser conocido desde el paso anterior y encontré tres objetivos para cada uno, estos objetivos se relacionaron con una visión de lo que quería para mi yo futuro.


El cuarto paso en el desarrollo de una marca personal es aprender analizando sus métricas de éxito y comprendiendo cómo lo ha hecho. Este es un paso simple que a menudo se olvida, pero es crucial para todo el proceso de desarrollo de la marca. Por lo general, solo pongo una cita en mi agenda y reflexiono internamente o en voz alta con un amigo o colega de confianza. Encuentro que siempre puedo aprender algo nuevo de la reflexión y descubrir qué puedo incorporar en la próxima iteración de mi marca.

Introduciendo: M.U. Tutors Licensing

M.U. Tutors es un mercado de tutores y estudiantes online, que permite buscar rápidamente al tutor ideal para ese examen o asignación próxima.

Como colaborador activo del proyecto, me complace anunciar un modelo de licenciamiento para el producto, ideal para universidades, escuelas y academias que manejan clases particulares o programas de tutorías. Esto significa que la institución dueña de la licencia, lo es también de los datos y la plataforma donde corre el sistema, originalmente ideado como SAAS.

Puede visitar para conocer mas detalles de la licencia.

Firefox Quantum y el lenguaje Rust

Rust es un lenguaje de programación compilado, de propósito general y multiparadigma que está siendo desarrollado por Mozilla.​ Ha sido diseñado para ser «un lenguaje seguro, concurrente y práctico».​​

El Logo de Rust

El nuevo Firefox Quantum incluye Stylo, un motor de CSS escrito en Rust, que aprovecha al máximo la «Concurrencia Libre de Miedo» de Rust para acelerar el estilizado de la página. Es el primer componente principal de Servo que se integra con Firefox y representa un hito importante para Servo, Firefox y Rust. Reemplaza aproximadamente 160,000 líneas de C ++ con 85,000 líneas de Rust.

Firefox Quantum


Se puede leer mas al respecto de Rust y su «Fearless Concurrency» en el blog de Rust: