---
title: "Taller Analytics y ML"
canonical: "https://onesaitplatform-es.refined.site/space/DOC/2216109855/Taller%20Analytics%20y%20ML"
format: markdown
---
> Macro (toc)

# 1. Introducción

El objetivo de este taller es aprender a usar diferentes componentes de la plataforma onesait Platform para completar el flujo de un **proceso de analítica de información**, desde la ingesta, pasando por el ML hasta la visualización.

Se parte de un dataset de la plataforma Kaggle [https://www.kaggle.com/mylesoneill/game-of-thrones](https://www.kaggle.com/mylesoneill/game-of-thrones) así como de kernels del mismo [https://www.kaggle.com/shaildeliwala/exploratory-analysis-and-predictions](https://www.kaggle.com/shaildeliwala/exploratory-analysis-and-predictions) y [https://www.kaggle.com/zhy450324080/death-prediction-battle-analysis](https://www.kaggle.com/zhy450324080/death-prediction-battle-analysis).

  
Se compondrá de los siguientes pasos:  
 

- Ingesta y preparación de los datos:
  - Creación de las ontologías con las que se trabajará
  - Creación de un DigitalClient para acceder a las ontologías
  - Se tendrán 3 tipos de ingesta de información:
    - Import tool
    - Dataflow
    - Notebook
- Data analytics & exploration & ML de los datos cargados mediante los notebooks de la plataforma
- Visualización de los datos mediante los dashboards de la plataforma

  
Para este taller se usarán los siguientes datasets:

- **character-predictions.csv** que se cargará desde la herramienta de Importación del Control Panel (Import Tool)
- **battles.csv** cargado desde el componente DataFlow
- **character-deaths.csv** que se cargará desde el componente Notebooks

Se presuponen conocimientos de programación (el Python principalmente) y la realización del taller IoT por lo que no se explicarán conceptos básicos de la plataforma.  
Para este taller es necesario disponer de un usuario en el entorno CloudLab con **Rol Analytics.**

# 2. Ingesta de información

En este capítulo se va a realizar la ingesta de los ficheros del dataset a través de diversas herramientas incluidas en la plataforma (cada una adecuada a diversos ámbitos).

## Carga puntual desde la herramienta Import Tool

La herramienta Import Tool de la plataforma provee una forma sencilla de crear ontologías infiriendo los esquemas de datos desde ficheros **json, csv, xls, xlsx o xml** y cargando los mismos de forma automática. También puede usarse tanto para cargar datos en una ontología existente, como para la creación vacía de la misma.  
El primer paso desde un usuario analytics, ya logado en la plataforma, será acceder al menú del mismo:  
> Macro (inline-media-image)

  
Dentro, vemos una simple interfaz con dos columnas destacadas, a la izquierda los datos (o un resumen de los mismos) que se cargarán y a la derecha el esquema inferido.  
Seleccionaremos el fichero a subir en forma de ontología, en nuestro caso será el siguiente:  


  
Para descargarlo, podemos hacer doble click en el mismo y guardarlo después en alguna carpeta. Este mismo fichero será el que seleccionemos cuando demos click en "Select File To Upload".  
> Macro (inline-media-image)

  
> Macro (inline-media-image)

> Macro (inline-media-image)

  
Se puede observar que el csv ha sido leído y transformado correctamente a formato JSON. El siguiente paso será darle a Generate Schema y podremos ver el esquema de ontología inferido automáticamente por la herramienta.  
> Macro (inline-media-image)

  
Como último paso de esta sección teniendo New Ontology y Import Data To RTDB marcados  
> Macro (inline-media-image)

  
Daremos abajo a Submit y nos aparecerá un popup para introducir el nombre de la ontología, descripción de la misma y la base de datos sobre la que irá. Es importante tener un nombre de ontología propio ya que la plataforma no permite dos ontologías con el mismo nombre:

- **Nombre**: ws_got_{fecha}_{usuario}_deaths
- **Descripción**: La que el usuarios quiera.
- **Datasource**: MONGO

> Macro (inline-media-image)

   
Una barra de progreso nos indicará el estado de la carga. Cuando ésta termine, se nos notificará.  
Para ver los datos que acaban de cargarse podemos dirigirnos a la herramienta Query Tool y lanzar la query por defecto que tenemos:  
> Macro (inline-media-image)

  
Seleccionamos la ontología que acabamos de crear y cargar:  
> Macro (inline-media-image)

  
> Macro (inline-media-image)

  
Finalmente ejecutamos la query por defecto generada con "Execute query":  
> Macro (inline-media-image)

  
Podemos observar cómo, en cada instancia, se han cargado los datos correspondientes a cada fila del csv inicial. Se puede ver también que, si un campo no está incluido en la fila, no llegará a la ontología destino.

## ETL/Streaming desde la herramienta Dataflow

La herramienta Dataflow se basa en el software open-source Streamsets ([https://streamsets.com/](https://streamsets.com/)).

Esta herramienta permite, de forma visual, modelar ETLs y flujos streaming de datos, así como controlarlos, ver los logs de los mismos...

Los datos entrarán por un origen único seleccionado y podrán ir a uno o varios destinos. Entre muchos otros, se permite tanto origen como destino la propia plataforma mediante el nodo "**onesait Platform**" correspondiente.  
En este caso no podremos inferir el esquema automáticamente y por tanto debemos crear tanto una ontología como un Digital Client asociado (estos pasos se obvian ya que se presupone este conocimiento del taller de IoT).

  
Los datos de la ontología destino será el siguiente:  
**Nombre**: ws_got_{date}_{user}_battle  
**Esquema**: General > EmptyBase (una vez seleccionado dar a update schema y pegar el siguiente esquema)  
**Esquema** (incluir al crear la nueva ontología):  
<span style="color: #0000ff">*{*</span>  
<span style="color: #0000ff">*"properties": {*</span>  
<span style="color: #0000ff">*"name": {*</span>  
<span style="color: #0000ff">*"type": "string"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"year": {*</span>  
<span style="color: #0000ff">*"type": "number"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"attacker_king": {*</span>  
<span style="color: #0000ff">*"type": "string"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"defender_king": {*</span>  
<span style="color: #0000ff">*"type": "string"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"attacker_1": {*</span>  
<span style="color: #0000ff">*"type": "string"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"defender_1": {*</span>  
<span style="color: #0000ff">*"type": "string"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"attacker_outcome": {*</span>  
<span style="color: #0000ff">*"type": "string"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"battle_type": {*</span>  
<span style="color: #0000ff">*"type": "string"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"major_death": {*</span>  
<span style="color: #0000ff">*"type": "number"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"major_capture": {*</span>  
<span style="color: #0000ff">*"type": "number"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"attacker_size": {*</span>  
<span style="color: #0000ff">*"type": "number"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"defender_size": {*</span>  
<span style="color: #0000ff">*"type": "number"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"attacker_commander": {*</span>  
<span style="color: #0000ff">*"type": "string"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"defender_commander": {*</span>  
<span style="color: #0000ff">*"type": "string"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"summer": {*</span>  
<span style="color: #0000ff">*"type": "number"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"location": {*</span>  
<span style="color: #0000ff">*"type": "string"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"region": {*</span>  
<span style="color: #0000ff">*"type": "string"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"note": {*</span>  
<span style="color: #0000ff">*"type": "string"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"attacker_2": {*</span>  
<span style="color: #0000ff">*"type": "string"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"attacker_3": {*</span>  
<span style="color: #0000ff">*"type": "string"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"attacker_4": {*</span>  
<span style="color: #0000ff">*"type": "string"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"defender_2": {*</span>  
<span style="color: #0000ff">*"type": "string"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"defender_3": {*</span>  
<span style="color: #0000ff">*"type": "string"*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"defender_4": {*</span>  
<span style="color: #0000ff">*"type": "string"*</span>  
<span style="color: #0000ff">*}*</span>  
<span style="color: #0000ff">*},*</span>  
<span style="color: #0000ff">*"type": "object",*</span>  
<span style="color: #0000ff">*"description": "Info workshop_got_battle",*</span>  
<span style="color: #0000ff">*"$schema": "http://json-schema.org/draft-04/schema#",*</span>  
<span style="color: #0000ff">*"title": "ws_240119_User01_battle",*</span>  
<span style="color: #0000ff">*"additionalProperties": false*</span>  
<span style="color: #0000ff">*}*</span><span style="color: #0000ff"> </span>

  
Una vez creada la ontología y un DigitalClient para poder acceder a la misma, pasamos a la creación de nuestro primer DataFlow:   
> Macro (inline-media-image)

  
Nos aparecerá el listado de los mismos y tendremos que dar click en crear uno nuevo arriba a la derecha.   
> Macro (inline-media-image)

  
Daremos el nombre de: **ws_got_{date}_{user}_ingestion** y daremos a OK.  
> Macro (inline-media-image)

   
Una vez cargado el lienzo, podemos observar la pantalla de edición del mismo.  
> Macro (inline-media-image)

  
Mediante la paleta de elementos de la derecha podremos ir construyendo nuestro flujo.   
El primer paso será solucionar uno de los errores que aparecen en pantalla, la forma en que el pipeline actual trata con los registros erróneos. Para ello nos tendremos que situar en la pestaña de Error Records y elegir Discard ya que no queremos hacer nada con esos registros en el caso de que existieran.  
> Macro (inline-media-image)

  
Con esto resuelto, pasamos a incluir nuestro origen de datos.

En este caso, se tiene en la ruta del contenedor del componente Dataflow, un volumen compartido con los datos que queremos ingestar, en una ruta del sistema de ficheros Unix. Para poder ingestar este fichero de datos usaremos el origin "Directory" dentro de Origins. Arrastrando y soltando lo tendremos en el lienzo.   
> Macro (inline-media-image)

   
Configuraremos la ruta origen con el path:   
**/data/workshop**   
Y el file patter pondremos el fichero directamente:   
**battle.csv**   
> Macro (inline-media-image)

   
  
  
Se trata de un fichero **csv** estándar separado por comas con cabecera, por lo que pasamos a especificar este formato en la pestaña Data Format (dentro de Configuración).  
> Macro (inline-media-image)

   
Al ser un fichero estándar no será necesario especificar nada más que eso y que queremos usar la cabecera del mismo (With Header Line). Por lo que pasamos a nuestro primer inicio del flujo. Esto no será posible sin un destino, por lo que usaremos a modo debug el Destination "**Trash**" y lo conectaremos con nuestro origen "**Directory 1**". Al unir ambos, no debería aparecer ningún error en el flujo:   
> Macro (inline-media-image)

  
Por lo que podemos pasar a validarlo y ver que nuestro flujo está listo para arrancar:  
> Macro (inline-media-image)

   
Si es correcto, nos lo indicará. A posteriori, vamos a ver los datos que entran en el flujo, por lo que en vez de arrancarlo vamos a hacer una preview del mismo:   
> Macro (inline-media-image)

   
Con los parámetros por defecto daremos a **Run Preview:**  
> Macro (inline-media-image)

   
Podremos ver como los campos se estructuran en registros y ver como estos van cambiando en cada fase del proceso, por lo que podremos depurar de forma visual nuestro flujo.   
> Macro (inline-media-image)

   
Una vez visto cómo podemos depurar y ver nuestro flujo, lo completaremos.

Si observamos la estructura que nos devuelve **Directory**, vemos que nos sobra el campo **battle_number** y que todos los campos son de tipo String, por lo que tendremos que convertir los oportunos a integer, para que puedan ser correctamente ingestados. También vemos que hay campos que vienen vacíos, por lo que, por sencillez, haremos que se sustituyan por -1 en todos los casos. 

Primero, incluiremos una nueva etapa en nuestro flujo para convertir estos vacíos en -1. Esto, será posible, gracias al Processor "**Field Replacer**". En este caso para poder hacerlo de forma masiva, una vez añadido incluiremos esto dentro de la pestaña **Replace**:   
<span style="color: #0000ff">**/*[${f:value() == ""}]**</span>** **  
Y pondremos el new value a -1   
> Macro (inline-media-image)

   
La siguiente etapa será la de convertir los campos numéricos al formato Integer. Para ello usaremos otro processor "**Field Type Converter**".   
Antes de configurar nada más, uniremos los 3 elementos en orden, de manera que gracias a esto se nos facilitará la selección de campos en el último elemento añadido. Iremos a la pestaña Conversions e incluiremos los campos siguientes a formato Integer (si no aparecen hay que recordar que hay que incluir una / delante de cada campo):

- <span style="color: #0000ff">year</span>
- <span style="color: #0000ff">major_death</span>
- <span style="color: #0000ff">major_capture</span>
- <span style="color: #0000ff">attacker_size</span>
- <span style="color: #0000ff">defender_size</span>
- <span style="color: #0000ff">summer</span>

  
> Macro (inline-media-image)

   
Como penúltimo paso, vamos a eliminar el campo battle_number, ya que nuestra ontología no lo tiene y no lo creemos necesario. Lo haremos con el Processor "**Field Remover**":   
> Macro (inline-media-image)

  
Finalmente vamos a incluir como destino el nodo de la plataforma en "destinations" llamado "Onesaitplatform Destination", el cual configuraremos de la siguiente manera:   
**Protocol**: http  
**Host**: [i](http://www.onesaitplatform.online)otbrokerservice  
**Port**: 19000  
**Token**: (el token que nos ha generado el Digital Client para la ontología que hemos creado y tenemos asociada con el mismo)  
**IoT Client**: Nombre del Digital Client que hemos creado

**IoT Client ID**: Podemos dejar el autogenerado  
**Ontology**: Nombre de la ontología que hemos creado   
> Macro (inline-media-image)

   
En la pestaña Destination del componente dejaremos los valores por defecto.

Finalmente arrancaremos el flujo y podremos ver en tiempo real como avanza la ingesta, throughtput de la carga, número de registros totales o en error…   
> Macro (inline-media-image)

   
Si hemos lanzado por error el flujo y vemos que no carga datos, podemos resetear el origen en los > Macro (inline-media-image)

que aparecen. Esto es debido a que Streamsets mantiene un cursor sobre el último fichero leído y la posición para no realizar lecturas duplicadas.   
> Macro (inline-media-image)

   
  
Podremos comprobar con el Query Tool de nuevo que la carga ha sido correcta.  
> Macro (inline-media-image)

   
Una vez terminada esta sección y cargados los datos, se parará el flujo mediante el botón de stop:   
> Macro (inline-media-image)



  


## Carga desde la herramienta Notebooks para Data Scientists

Esta sección servirá de introducción a la herramienta de notebooks de la plataforma y de la siguiente sección.

  


Lo primero que haremos será subir un nuevo fichero a la herramienta **My Files** de la plataforma.   
> Macro (inline-media-image)

  
Con esta herramienta, se pueden disponibilizar ficheros de forma sencilla y securizada por **URL** y gestionarlos desde la plataforma, usarlos desde terceros y otros componentes de la plataforma como son los notebooks.   
> Macro (inline-media-image)

   
Daremos a **Create **y seleccionaremos el siguiente fichero que debemos haber bajado a nuestro ordenador, el resto de parámetros por defecto y a submit .  
  


   
Con esto aparecerá el fichero en nuestro listado.   
> Macro (inline-media-image)

   
Lo último, por sencillez, lo que tenemos que hacer, será darle a **public** para poder hacer el fichero público y leerlo sin autenticación.

Una vez hecho esto podemos darle a "**Copy URL to Clipboard**" ya que la necesitaremos en los siguientes pasos.

  
Ahora, vamos a crear nuestro primer Notebook en la plataforma. Este ecosistema está basado en Apache Zeppelin en su última versión ([https://zeppelin.apache.org/](https://zeppelin.apache.org/)). Provee notebooks para analítica, visualización inline, ejecución de algoritmos y muchas opciones más, en un entorno multiusuario, colaborativo, versionado, ejecutable tanto en remoto, puntual o temporizado, controlado y con capacidad de ejecutar diferentes lenguajes de programación y comunicarlos entre sí.   
> Macro (inline-media-image)

   
Se compone de **párrafos** en cada cual se incluye un "**intérprete**" con la notación %interprete. Cada tipo de interprete tiene diferentes asignaciones, desde ejecutar un cierto lenguaje de programación como Python, scala o R o lanzar queries contra una base de datos, un SparkQL, Neo4J, ejecutar comandos Shell o pintar HTML en la pantalla del usuario.   
Para entenderlo lo mejor el verlo en acción. Vamos a My notebooks y damos a Crear nuevo notebook :   
> Macro (inline-media-image)

   
> Macro (inline-media-image)

   
Le daremos el nombre de **ws_got_{date}_{user}_analytics** y al crearlos llegaremos a la siguiente pantalla   
> Macro (inline-media-image)

  
Nuestro objetivo, va a ser, en el lenguaje **Python**, usando la librería de **pandas** (librería de dataframes de python) cargar el archivo que anteriormente hemos subido a la plataforma como dataframe e insertarlo en la plataforma con una nueva ontología.

En la siguiente sección jugaremos con este dataframe para hacer visualizaciones inline y algoritmos de ML.

  
Lo primero, crearemos esta última ontología y la asociaremos nuestro DigitalClient. El nombre y el esquema son los siguientes. Se crearía de la misma manera que la anterior del ejercicio de Dataflow.   
<span style="color: #0000ff">**Nombre**</span><span style="color: #0000ff">: ws_got_{date}_{user}_cdeads</span>  
<span style="color: #0000ff"> </span><span style="color: #0000ff">**Esquema**</span><span style="color: #0000ff">: </span>  
{  
"properties": {  
"sNo": {  
"type": "number"  
},  
"actual": {  
"type": "number"  
},  
"pred": {  
"type": "number"  
},  
"alive": {  
"type": "number"  
},  
"plod": {  
"type": "number"  
},  
"name": {  
"type": "string"  
},  
"male": {  
"type": "number"  
},  
"mother": {  
"type": "string"  
},  
"father": {  
"type": "string"  
},  
"heir": {  
"type": "string"  
},  
"book1": {  
"type": "number"  
},  
"book2": {  
"type": "number"  
},  
"book3": {  
"type": "number"  
},  
"book4": {  
"type": "number"  
},  
"book5": {  
"type": "number"  
},  
"isAliveMother": {  
"type": "number"  
},  
"isAliveFather": {  
"type": "number"  
},  
"isAliveHeir": {  
"type": "number"  
},  
"isMarried": {  
"type": "number"  
},  
"isNoble": {  
"type": "number"  
},  
"numDeadRelations": {  
"type": "number"  
},  
"boolDeadRelations": {  
"type": "number"  
},  
"isPopular": {  
"type": "number"  
},  
"popularity": {  
"type": "number"  
},  
"isAlive": {  
"type": "number"  
}  
},  
"type": "object",  
"description": "Info workshop_got_cpred",  
"$schema": "[http://json-schema.org/draft-04/schema#](http://json-schema.org/draft-04/schema)",  
"title": "workshop_got_cpred",  
"additionalProperties": true  
}

  
Con esta ontología creada y asociada al Digital Client volvemos a nuestro notebook.   
Como vemos, tenemos el cursor en el primer párrafo, lo primero que haremos será import de la librería pandas en Python por lo que el párrafo tiene que in precedido por **%python**.

<span style="color: #0000ff">%python</span>  
<span style="color: #0000ff"> import pandas as pd</span>  
<span style="color: #0000ff"> import os, ssl </span>

  
> Macro (inline-media-image)

   
Para organizar nuestro trabajo, pondremos un título al párrafo para recordar lo que hacía si lo volvemos a usar.   
> Macro (inline-media-image)

   
> Macro (inline-media-image)

   
Como vemos vamos a usar un par de librerías más,** os y ssl,** que nos ayudarán a acceder de forma insegura al fichero.

Este párrafo lo podemos ejecutar ya mediante el botón > Macro (inline-media-image)

 (**Play)** de la derecha del mismo o con el cursor en el mismo **shift+enter**. Vemos que pasa casi instantáneamente del estado **Ready** a **Finished** lo cual nos indica el fin de la ejecución del párrafo   
> Macro (inline-media-image)

   
En el siguiente párrafo, también de Python, haremos la carga en una línea del fichero remoto en un pandas dataframe.   
Añadimos un nuevo párrafo al que titularemos load cdeath file into pandas:

```python
%python
if (not os.environ.get('PYTHONHTTPSVERIFY', '') and
    getattr(ssl, '_create_unverified_context', None)): 
    ssl._create_default_https_context = ssl._create_unverified_context
character_deaths = pd.read_csv("url del fichero copiada")
```

  
Y lo ejecutamos.   
> Macro (inline-media-image)

   
Si no nos da ningún error significa que ha cargado correctamente el fichero. Las 3 primeras líneas son para desactivar la verificación ssl en Python y evitar un error de certificados. Debemos poner correctamente la url del fichero **público** que hemos subido.   
Si queremos ver los datos, no hace falta más que escribir el nombre del dataframe (character_deaths) en un tercer párrafo y ejecutarlo.   
> Macro (inline-media-image)

   
Finalmente como, de momento, nuestro objetivo es insertar datos en la plataforma vamos a transformar este dataframe de pandas en un json válido, quitaremos los datos NA por tipo de campo y será compatible con la ontología. En la segunda línea incluido este String JSON en una variable del contexto de zeppelin que nos servirá para comunicarnos entre lenguajes:

<span style="color: #3366ff">%python</span>  
<span style="color: #3366ff">character_deaths[['sNo','actual','pred','alive','plod','male','dateOfBirth','dateoFdeath','book1','book2','book3','book4','book5','isAliveMother','isAliveFather','isAliveHeir','isAliveSpouse','isMarried','isNoble','age','numDeadRelations','boolDeadRelations','isPopular','popularity','isAlive']] = character_deaths[['sNo','actual','pred','alive','plod','male','dateOfBirth','dateoFdeath','book1','book2','book3','book4','book5','isAliveMother','isAliveFather','isAliveHeir','isAliveSpouse','isMarried','isNoble','age','numDeadRelations','boolDeadRelations','isPopular','popularity','isAlive']].fillna(-1)</span>

<span style="color: #3366ff">character_deaths[['name','title','culture','mother','father','heir','house','spouse']] = character_deaths[['name','title','culture','mother','father','heir','house','spouse']].fillna("")</span>  
<span style="color: #3366ff">jsondataframe = character_deaths.to_json(orient="records")</span>  
<span style="color: #3366ff">z.z.put("instances",jsondataframe)</span>

![image](media://879a7619-cca4-480e-8fd3-45c751ea0bef)

Para poder interactuar con la plataforma, se dispone del intérprete **%onesaitplatform**. Para poder iniciar esta interacción necesitamos lo primero iniciar una conexión con la plataforma de la siguiente forma:

<span style="color: #0000ff">%onesaitplatform</span>  
<span style="color: #0000ff"> initConnection("IoT Client","Access token") </span>

  


De modo que si nuestros parámetros son correctos podemos acceder a nuestras ontologías al ejecutarlo. Por seguridad, la conexión termina a los minutos por lo que si otras instrucciones de la plataforma dan problemas y puede ser necesario ejecutar de nuevo este párrafo de nuevo   
> Macro (inline-media-image)

   
Finalmente, como tenemos la conexión hecha con la plataforma ejecutamos también con el intérprete onesaitplatform y gracias también al zeppelin context insertamos los datos en la ontología destino:

<span style="color: #0000ff">%onesaitplatform</span>  
<span style="color: #0000ff"> insert("</span><span style="color: #0000ff">**{nueva ontologia creada}**</span><span style="color: #0000ff">",z.get("instances")) </span>

  
> Macro (inline-media-image)

   
Podemos comprobar con el Query Tool de Nuevo que nuestra ontología se ha cargado de datos.   
> Macro (inline-media-image)



# 3. Data analytics & exploration & ML de los datos cargados mediante los notebooks de la plataforma

En esta sección realizaremos una breve exploración de los datos que hemos cargado en el dataframe character_deaths.   
Partiendo del notebook creado anteriormente, podemos empezar a ver los datos que contiene el mismo. Lo primero, usaremos un nuevo intérprete (**markdown**) para escribir HTML de forma sencilla y delimitar las secciones. La # significa h1 en HTML es decir un texto cabecera grande.  
> Macro (inline-media-image)

   
Ahora iremos añadiendo consecutivamente párrafos **%python** para ir viendo el dataframe   
**Longitud del dataframe:**

<span style="color: #0000ff">%python</span>  
<span style="color: #0000ff"> character_deaths.size</span>   
> Macro (inline-media-image)

   
**Tamaño del mismo **  
<span style="color: #0000ff">%python</span>  
<span style="color: #0000ff"> character_deaths.shape </span>  
> Macro (inline-media-image)

   
**Mostrar sólo la cabecera **  
<span style="color: #0000ff">%python</span>  
<span style="color: #0000ff"> print character_deaths.head(1) </span>  
> Macro (inline-media-image)

   
Aumentar el máximo de columnas visibles y ver datos estadísticos de cada columna   
<span style="color: #0000ff">%python</span>  
<span style="color: #0000ff"> pd.set_option('display.max_columns', 100)</span>  
<span style="color: #0000ff"> character_deaths.describe() </span>  
> Macro (inline-media-image)

  
Se pueden ir haciendo infinidad de transformaciones, procesamientos y visualizaciones de Python con pandas, incluso unir unos dataframes con otros, etc,...   
Ahora pasaremos a usar el motor SQL sobre pandas de los notebooks con **%python.sql**, para poder graficar instantáneamente los datos como si de una base de datos se tratara. Sólo hace falta definir una variable que sea dataframe, en nuestro caso **character_deaths** y lanzar queries sobre la misma haciéndonos preguntas:   
**Most popular characters** **by** **house**   
<span style="color: #0000ff">%python.sql</span>  
<span style="color: #0000ff"> select name, house, popularity from character_deaths where House!="None" order by popularity desc limit 50</span>  
> Macro (inline-media-image)

   
Podemos observar la visualización en formato tabla. Pero mediante un gráfico de barras podemos llegar a una visualización más interesante:   
> Macro (inline-media-image)

  
> Macro (inline-media-image)

  
O **ver la casas más populares** en formato pie:   
<span style="color: #0000ff">%python.sql</span>  
<span style="color: #0000ff"> select house, sum(popularity) as phouse from character_deaths where House!="None" group by House order by phouse desc limit 10</span>  
> Macro (inline-media-image)

  
> Macro (inline-media-image)

   
O el top de casas con más gente viva:   
<span style="color: #0000ff">%python.sql</span>  
<span style="color: #0000ff"> select house, sum(isAlive) as alivecount from character_deaths group by house order by alivecount desc limit 10 </span>  
> Macro (inline-media-image)

   
También es possible hacer estas queries o visualizaciones directamente contra ontologías de la plataforma con el intérprete de la misma.

<span style="color: #0000ff">%onesaitplatform</span>  
<span style="color: #0000ff"> select region, count(*) as c from </span><span style="color: #0000ff">**{battle_ontology}**</span><span style="color: #0000ff"> as c group by region limit 10 </span>  
> Macro (inline-media-image)

  
Mediante asZTable se activa la visualización built-in:

<span style="color: #0000ff">%onesaitplatform</span>  
<span style="color: #0000ff"> asZTable(select region, count(*) as c from </span><span style="color: #0000ff">**{battle_ontology} **</span><span style="color: #0000ff">as c group by region limit 10) </span>  
> Macro (inline-media-image)

  
Como será útil en la siguiente sección, vamos a guardar como pandas los datos de la ontología del fichero battle de la siguiente forma:   
<span style="color: #0000ff">%onesaitplatform</span>  
<span style="color: #0000ff"> z.put("battleData", select year,attacker_outcome,summer,major_death,attacker_commander,attacker_4,attacker_3,attacker_2,attacker_1,defender_4,defender_3,defender_2,defender_1,defender_size,defender_king,battle_type,attacker_size,name,attacker_king,defender_commander,location,major_capture,region from </span><span style="color: #0000ff">**{battle_ontology}**</span><span style="color: #0000ff">) </span>  
> Macro (inline-media-image)

   
Y lo pasaremos a dataframe de pandas después:   
<span style="color: #0000ff">%python</span>  
<span style="color: #0000ff"> import json</span>  
<span style="color: #0000ff"> from pandas.io.json import json_normalize </span>  
<span style="color: #0000ff"> lbattle = list(z.z.get("battleData"))</span>  
<span style="color: #0000ff"> battles = json_normalize(list(map(lambda x: json.loads(x), lbattle))) </span>  
> Macro (inline-media-image)

   
Finalmente, para terminar la parte de data exploratory podemos usar potentes gráficos de las librerías de Python como **matplotlib** o **seaborn**.

Están librerías nos darán aún más libertad que la visualización built-in a costa de escribir más código para construir el gráfico objetivo.  
**Importamos** **nuevas** **librerías**   
<span style="color: #0000ff">%python</span>  
<span style="color: #0000ff"> import numpy as np</span>  
<span style="color: #0000ff"> import seaborn as sns</span>  
<span style="color: #0000ff"> import matplotlib as mpl</span>  
<span style="color: #0000ff"> import matplotlib.pyplot as plt</span>  
<span style="color: #0000ff"> from collections import Counter</span>  
<span style="color: #0000ff"> import matplotlib.patches as mpatches</span>  
<span style="color: #0000ff"> sns.set_style("white") </span>  
**Generamos nuevos atributos**   
<span style="color: #0000ff">%python</span>  
<span style="color: #0000ff"> character_predictions = character_deaths.copy(deep = True)</span>  
<span style="color: #0000ff"> battles.loc[:, "defender_count"] = (4 - battles[["defender_1", "defender_2", "defender_3", "defender_4"]].isnull().sum(axis = 1))</span>  
<span style="color: #0000ff"> battles.loc[:, "attacker_count"] = (4 - battles[["attacker_1", "attacker_2", "attacker_3", "attacker_4"]].isnull().sum(axis = 1))</span>  
<span style="color: #0000ff"> battles.loc[:, "att_comm_count"] = [len(x) if type(x) == list else np.nan for x in battles.attacker_commander.str.split(",")]</span>  
<span style="color: #0000ff"> character_predictions.loc[:, "no_of_books"] = character_predictions[[x for x in character_predictions.columns if x.startswith("book")]].sum(axis = 1) </span>  
**Major death/capture events by year**   
<span style="color: #0000ff">%python</span>  
<span style="color: #0000ff"> p = battles.groupby('year').sum()[["major_death", "major_capture"]].plot.bar(rot = 0)</span>  
<span style="color: #0000ff"> _ = p.set(xlabel = "Year", ylabel = "No. of Death/Capture Events", ylim = (0, 9)), p.legend(["Major Deaths", "Major Captures"]) </span>  
**Which pairs fought the most battles?**   
<span style="color: #0000ff">%python</span>  
<span style="color: #0000ff"> #Ignoring records where either attacker_king or defender_king is null. Also ignoring one record where both have the same value.</span>  
<span style="color: #0000ff"> c = list(Counter([tuple(set(x)) for x in battles.dropna(subset = ["attacker_king", "defender_king"])[["attacker_king", "defender_king"]].values if len(set(x)) > 1]).items())</span>  
<span style="color: #0000ff"> p = pd.DataFrame(c).sort_values(1).plot.barh(figsize = (10, 6))</span>  
<span style="color: #0000ff"> _ = p.set(yticklabels = ["%s vs. %s" % (x[0], x[1]) for x in list(zip(*c))[0]], xlabel = "No. of Battles"), p.legend("") </span>  
**How many commanders did armies of different kings have?**   
<span style="color: #0000ff">%python</span>  
<span style="color: #0000ff"> p = sns.boxplot("att_comm_count", "attacker_king", data = battles, saturation = .6, fliersize = 10., palette = ["lightgray", sns.color_palette()[1], "grey", "darkblue"])</span>  
<span style="color: #0000ff"> _ = p.set(xlabel = "No. of Attacker Commanders", ylabel = "Attacker King", xticks = range(8)) </span>

  
Por último, vamos generar varios **modelos de ML** con el objetivo de ver las herramientas de python que ya vienen en la plataforma integradas:   
**Data Cleansing**

```python
%python
#-------- Copy Again ----------

data = character_deaths.copy(deep = True)

#-------- culture induction -------
cult = {
    'Summer Islands': ['summer islands', 'summer islander', 'summer isles'],
    'Ghiscari': ['ghiscari', 'ghiscaricari',  'ghis'],
    'Asshai': ["asshai'i", 'asshai'],
    'Lysene': ['lysene', 'lyseni'],
    'Andal': ['andal', 'andals'],
    'Braavosi': ['braavosi', 'braavos'],
    'Dornish': ['dornishmen', 'dorne', 'dornish'],
    'Myrish': ['myr', 'myrish', 'myrmen'],
    'Westermen': ['westermen', 'westerman', 'westerlands'],
    'Westerosi': ['westeros', 'westerosi'],
    'Stormlander': ['stormlands', 'stormlander'],
    'Norvoshi': ['norvos', 'norvoshi'],
    'Northmen': ['the north', 'northmen'],
    'Free Folk': ['wildling', 'first men', 'free folk'],
    'Qartheen': ['qartheen', 'qarth'],
    'Reach': ['the reach', 'reach', 'reachmen'],
}

def get_cult(value):
    value = value.lower()
    v = [k for (k, v) in cult.items() if value in v]
    return v[0] if len(v) > 0 else value.title()

data.loc[:, "culture"] = [get_cult(x) for x in data.culture.fillna("")]

#-------- culture induction -------

data.drop(["name", "alive", "pred", "plod", "isAlive", "dateOfBirth", "dateoFdeath"], 1, inplace = True)

data.loc[:, "title"] = pd.factorize(data.title)[0]
data.loc[:, "culture"] = pd.factorize(data.culture)[0]
data.loc[:, "mother"] = pd.factorize(data.mother)[0]
data.loc[:, "father"] = pd.factorize(data.father)[0]
data.loc[:, "heir"] = pd.factorize(data.heir)[0]
data.loc[:, "house"] = pd.factorize(data.house)[0]
data.loc[:, "spouse"] = pd.factorize(data.spouse)[0]

data.fillna(value = -1, inplace = True)
''' $$ The code below usually works as a sample equilibrium. However in this case,
 this equilibirium actually decrease our accuracy, all because the original 
prediction data was released without any sample balancing. $$

data = data[data.actual == 0].sample(350, random_state = 62).append(data[data.actual == 1].sample(350, random_state = 62)).copy(deep = True).astype(np.float64)

'''
Y = data.actual.values

Odata = data.copy(deep=True)

data.drop(["actual"], 1, inplace = True)


```

  
**Feature Correlation**   
<span style="color: #0000ff">%python</span>  
<span style="color: #0000ff"> sns.heatmap(data.corr(),annot=True,cmap='RdYlGn',linewidths=0.2) #data.corr()-->correlation matrix</span>  
<span style="color: #0000ff"> fig=plt.gcf()</span>  
<span style="color: #0000ff"> fig.set_size_inches(30,20)</span>  
<span style="color: #0000ff"> plt.show() </span>

  
**RandomForest (over fit)**   
<span style="color: #0000ff">%python</span>  
<span style="color: #0000ff"> data.drop(["sNo"], 1, inplace = True)</span>  
<span style="color: #0000ff"> ''' ATTENTION: This rf algorithm achieves 99%+ accuracy, this is because the \</span>  
<span style="color: #0000ff"> original predictor-- the document releaser use exactly the same algorithm to predict!</span>  
<span style="color: #0000ff"> '''</span>  
<span style="color: #0000ff"> from sklearn.ensemble import RandomForestClassifier </span>  
  
<span style="color: #0000ff"> random_forest = RandomForestClassifier(n_estimators=100) </span>  
<span style="color: #0000ff"> random_forest.fit(data, Y) </span>  
<span style="color: #0000ff"> print('RandomForest Accuracy：(original)\n',random_forest.score(data, Y)) </span>

  
**DecisionTree**   
<span style="color: #0000ff">%python </span>  
<span style="color: #0000ff"> from sklearn.tree import DecisionTreeClassifier </span>  
<span style="color: #0000ff"> DT=DecisionTreeClassifier() </span>  
<span style="color: #0000ff"> DT.fit(data,Y) </span>  
<span style="color: #0000ff"> print('DecisionTree Accuracy：(original)\n',DT.score(data, Y)) </span>

  
**SVC**   
<span style="color: #0000ff">%python </span>  
<span style="color: #0000ff"> from sklearn.svm import SVC, LinearSVC</span>  
<span style="color: #0000ff"> svc = SVC() </span>  
<span style="color: #0000ff"> svc.fit(data, Y) </span>  
<span style="color: #0000ff"> print('SVC Accuracy：\n',svc.score(data, Y)) </span>

  
**LogisticRegression**   
<span style="color: #0000ff">%python</span>  
<span style="color: #0000ff"> from sklearn.linear_model import LogisticRegression </span>  
<span style="color: #0000ff"> LR = LogisticRegression() </span>  
<span style="color: #0000ff"> LR.fit(data, Y) </span>  
<span style="color: #0000ff"> print('LogisticRegression Accuracy：\n',LR.score(data, Y)) </span>

  
**KNN**   
<span style="color: #0000ff">%python </span>  
<span style="color: #0000ff"> from sklearn.neighbors import KNeighborsClassifier </span>  
<span style="color: #0000ff"> knn = KNeighborsClassifier(n_neighbors = 3) </span>  
<span style="color: #0000ff"> knn.fit(data, Y) </span>  
<span style="color: #0000ff"> print('kNN Accuracy：\n',knn.score(data, Y)) </span>

  
**NaiveBayes Gaussian**   
<span style="color: #0000ff">%python</span>  
<span style="color: #0000ff"> from sklearn.naive_bayes import GaussianNB </span>  
<span style="color: #0000ff"> gaussian = GaussianNB() </span>  
<span style="color: #0000ff"> gaussian.fit(data, Y) </span>  
<span style="color: #0000ff"> print('gaussian Accuracy：\n',gaussian.score(data, Y)) </span>

  
**RandomForest with CrossValidation**   
<span style="color: #0000ff">%python</span>  
<span style="color: #0000ff">from sklearn.model_selection import cross_validate</span>  
<span style="color: #0000ff">from sklearn.model_selection import KFold</span>  
<span style="color: #0000ff">from sklearn.model_selection import cross_val_score</span>  
<span style="color: #0000ff">from sklearn.ensemble import RandomForestClassifier</span>  
<span style="color: #0000ff">predictors=['title', 'culture', 'mother', 'father', 'heir', 'house', 'spouse', 'male', 'book1', 'book2', 'book3', 'book4', 'book5', 'isAliveFather', 'isAliveMother', 'isAliveHeir', 'isAliveSpouse', 'isMarried', 'isNoble', 'age', 'numDeadRelations', 'boolDeadRelations', 'isPopular', 'popularity']</span>  
<span style="color: #0000ff">alg=RandomForestClassifier(random_state=1,n_estimators=150,min_samples_split=12,min_samples_leaf=1)</span>  
<span style="color: #0000ff">kf=KFold(n_splits=3,random_state=1)</span>  
<span style="color: #0000ff">kf=kf.get_n_splits(Odata.shape[0])</span>  
<span style="color: #0000ff">scores=cross_val_score(alg,Odata[predictors],Odata["actual"],cv=kf)</span>  
<span style="color: #0000ff">print('RandomForest Accuracy：\n',scores.mean())</span>

# 4. Visualización de los datos mediante los dashboards de la plataforma

Nuestro objetivo en esta sección será el de usar el **motor de dashboards** integrado en la plataforma (se recomienda usar Google Chrome ya que el motor web, está optimizado para el mismo).

Generaremos una visualización con los datos cargados en los pasos anteriores. Estos dashboards generados podrán compartirse con diferentes usuarios, parametrizarse, hacerlos públicos y muchas opciones más.   
Primero, con un usuario ya logado vamos a crear nuestro primer dashboard, para ellos vamos a **My Dashboards** dentro del menú **Visualizations** y hacemos click en **Create Dashboard**.

Podemos observar que al entrar al menú vemos los dashboard públicos/propios o a los que nos han dado permiso.   
> Macro (inline-media-image)

   
> Macro (inline-media-image)

   
Dentro daremos el nombre a nuestro nuevo dashboard   
<span style="color: #0000ff">ws_got_{date}_{User01}_Visualization </span>  
> Macro (inline-media-image)

  
Por último, sin cambiar nada más, damos a "**New**" y nuestro dashboard estará creado. Lo podremos comprobar, ya que llegaremos a un lienzo vacía sobre el que incluiremos elementos denominados "**gadgets**" que recuperarán datos directamente desde las ontologías.   
> Macro (inline-media-image)

  
Vamos a crear nuestro primer gadget. En este caso vamos a crear un gadget **Pie** para ver la distribución de popularidad de las diferentes casas.

Este gadget nos servirá de filtro sobre otros del dashboard a futuro.   
Para ello vamos añadir un nuevo gadget con el botón :plus: arriba a la derecha. Veremos que nos aparece una banda con los gadgets disponibles en la plataforma:   
> Macro (inline-media-image)

   
Arrastraremos el tipo de gadget (Pie chart) dentro del lienzo, sobre la zona que queremos pintarlo. Al soltar nos aparecerá el siguiente popup, en el cual al no tener ningún gadget pie previamente creado daremos a "**New Gadget**"   
> Macro (inline-media-image)

   
Nos parecerá el formulario de creación del gadget, en el cual:   
**Nombre**: <span style="color: #0000ff">ws_got_240119_User01_pie</span>  
**Ontology or Datasource**: (nuestra ontología de deaths)   
> Macro (inline-media-image)

  
Como vemos, se nos dará una query por defecto.

Dejaremos lo primero Max Values a 10 y como queremos ver la popularidad de las casas, usaremos esta query:   
<span style="color: #0000ff">*select house, sum(popularity) as phouse from *</span><span style="color: #0000ff">***{ontología cdeaths}***</span><span style="color: #0000ff">* where house!= -1 and house!="None" group by house order by phouse*</span><span style="color: #0000ff"> </span><span style="color: #0000ff">*desc limit 10*</span><span style="color: #0000ff"> </span>  
Con lo que tendremos agrupadas las casas por la popularidad total. Si ejecutamos la misma en el formulario podemos ver los resultados.   
> Macro (inline-media-image)

   
Damos a "Continue".   
> Macro (inline-media-image)

   
Finalmente seleccionamos los campos para nuestro pie:

**X Axis**: house

**Y Axis** :phouse

y damos a **New**.   
> Macro (inline-media-image)

   
> Macro (inline-media-image)

   
Mediante los bordes del mismo podemos redimensionar el elemento o moverlo en el lienzo mediante las flechas de la cabecera.   
> Macro (inline-media-image)

   
Crearemos rápido un par de gadgets más:   
El primero un mixed en el que veremos la popularidad individual de los personajes   
<span style="color: #000000">**Nombre:**</span><span style="color: #0000ff">** ws_got_{date}_{user}_mixed **</span>

<span style="color: #3366ff">select * from </span><span style="color: #3366ff">***{ontología cdeaths}***</span><span style="color: #3366ff"> order by popularity desc limit 10</span>

  
> Macro (inline-media-image)

   
Damos a Continue y ponemos la configuración que aparece en la imagen   
> Macro (inline-media-image)

   
> Macro (inline-media-image)

   
> Macro (inline-media-image)

   
Finalmente nos tiene que aparecer el siguiente gráfico:   
> Macro (inline-media-image)

   
El segundo una tabla a modo de logbook de batallas:   
**ws_got_240119_User01_table **  
**Query**: <span style="color: #0000ff">select name,attacker_1,defender_1, case note when "-1" then "" else note end as note from </span><span style="color: #3366ff">***{ontología battle}***</span><span style="color: #0000ff"> </span>  
> Macro (inline-media-image)

   
> Macro (inline-media-image)

  
Colocando todo deberíamos tener en nuestro dashboard algo como lo siguiente:   
> Macro (inline-media-image)

   
Vamos a relacionar los dos gadgets de arriba ya que, como vemos, es posible a nivel de datasource filtrar los personajes de la derecha desde la casas. Para ellos usaremos el > Macro (inline-media-image)

(**Datalink)**:   
> Macro (inline-media-image)

   
Pondremos como origen nuestro Pie y como destino nuestro Mixed. El campo de cruce será house en los dos casos:   
> Macro (inline-media-image)

   
Daremos al :plus: para añadir la conexión y al cerrar cualquier click en el pie nos filtrará el Gadget Mixed   
> Macro (inline-media-image)

   
> Macro (inline-media-image)

   
> Macro (inline-media-image)



  
Decorando un poco más el Dashboard podemos llegar a un resultado final como el siguiente:

  
> Macro (inline-media-image)

> Macro (anchor)