domingo, 11 de mayo de 2014

Curso Datastax - Cassandra: Practica 2

Aplicación web: Playlist

Ejercicio 1 - Creando un Keyspace: 'playlist'

Abrimos el shell de Cassandra desde el terminal:
  astwin@astwin-H87-HD3:~$ cqlsh
Creamos el keyspace llamado playlist:
CREATE KEYSPACE playlist WITH replication = {
  'class': 'SimpleStrategy',  'replication_factor': '1' };
Como trabajamos en local, el factor de réplica 1 (una sola copia de los datos introducidos) y la estrategia de replicación simple (sin múltiples 'data centers').
Utilizamos este keyspace a partir de ahora:
USE playlist ;

Ejercicio 2 - Creando y cargando datos en la tabla de artistas

Creamos tabla de artistas ordenados por la primera letra del nombre:
CREATE TABLE artists_by_first_letter (
  first_letter text,
  artist text,
  PRIMARY KEY (first_letter, artist)
);
Nos permitirá realizar consultas a través de la primera letra del nombre del artista. 
Cargamos los datos de artistas proporcionados en el archivo 'artists.csv': primera letra y nombre de artista separados por caracter ' | ':
A|ARRESTED DEVELOPMENT
A|Abe Vigoda
...
cqlsh:playlist> COPY artists_by_first_letter(first_letter , artist ) FROM '/home/astwin/Escritorio/Cassandra/Leccion 2/scripts/artists.csv' WITH DELIMITER = '|';
3605 rows imported in 1.694 seconds.
Comprobamos que los datos se han cargado mirando unos cuantos registros:

cqlsh:playlist> SELECT * FROM artists_by_first_letter LIMIT 3;
 first_letter | artist
--------------+---------------------------------
            C |                  C.W. Stoneking
            C |                            CH2K
            C | CHARLIE HUNTER WITH LEON PARKER
La consulta no proporciona los resultados en orden alfabético por primera letra (first_letter: partition key), pero sí lo realiza por nombre (artist: clustering key).
Un ejemplo de consulta por letra:
cqlsh:playlist> SELECT * FROM artists_by_first_letter WHERE first_letter='N' LIMIT 5;

Ejercicio 3 - Correr la aplicación en Eclipse y ver los artistas

Cargamos el proyecto Maven descargado desde la página del curso de Datastax en Eclipse. Lo ejecutamos (clase principal StartJetty class). Abrimos la aplicación web (local): http://localhost:8080/playlist. Abrimos el apartado: “VISIT THE SONG DATABASE”. Clickeamos en alguna letra para obtener los artistas que comienzan por esa letra (se utiliza la consulta a la tabla que creamos anteriormente):

Si intentamos obtener las canciones por artista obtendremos un error, puesto que no tenemos creada la tabla track_by_artist:

Ejercicio 4 - Crear y cargar datos en la base de datos de canciones por artista (track_by_artist)

Creamos la tabla de canciones por artista:
CREATE TABLE track_by_artist (
  artist text,
  genre text,
  music_file text,
  track text,
  track_id uuid,
  track_length_in_seconds int,
  PRIMARY KEY (artist,track_id)
);
Cargamos datos desde fichero 'songs.csv' (contiene header y separación '|'):
track_id|genre|artist|track|track_length_in_seconds|music_file
c8bbc608-07ab-4586-9ba4-bedbd829c66c|classic pop and rock|Blue Oyster Cult|Mes Dames Sarat|246|TRFCOOU128F427AEC0
b3805f45-4db8-4362-bf3d-7864cfdaa0c1|classic pop and rock|Blue Oyster Cult|Screams|189|TRNJTPB128F427AE9F
....
cqlsh:playlist> COPY track_by_artist (track_id, genre, artist, track, track_length_in_seconds, music_file) FROM '/home/astwin/Escritorio/Cassandra/Leccion 2/scripts/songs.csv' WITH DELIMITER = '|' AND HEADER=true;
59600 rows imported in 16.323 seconds.
 Ahora comprobamos que ya podemos obtener las canciones por artista en la aplicación web (por ejemplo, miramos Camilo Sesto):

Ejercicio 5 - Implementar un comando 'select'

Si vamos a la letra P y al artista “Pagan's Mind” obtenemos una excepcion CQL:
Observamos el error:

com.datastax.driver.core.exceptions.SyntaxError: line 1:59 mismatched character '<EOF>' expecting '''
 at com.datastax.driver.core.exceptions.SyntaxError.copy(SyntaxError.java:35)
 at com.datastax.driver.core.ResultSetFuture.extractCauseFromExecutionException(ResultSetFuture.java:271)
 at com.datastax.driver.core.ResultSetFuture.getUninterruptibly(ResultSetFuture.java:187)
 at com.datastax.driver.core.Session.execute(Session.java:126)
 at com.datastax.driver.core.Session.execute(Session.java:77)
 at playlist.model.TracksDAO.listSongsByArtist(TracksDAO.java:65)
Si vamos al código Java del método listSongsByArtist, vemos que se realiza una consulta utilizando la API de Cassandra:
    String queryText = "SELECT * FROM track_by_artist WHERE artist = '" + artist + "'";
    ResultSet results = getSession().execute(queryText);
La consulta se crea de forma simple, utilizando un String, concatenando la consulta con la variable artist. En este caso, al contener la variable artist una comilla simple (Pagan's Mind), la consulta creada será errónea para CQL:
SELECT * FROM track_by_artist WHERE artist ='Pagan's Mind';
Necesitamos arreglar la consulta utilizando la API de Java con una consulta preparada (PreparedStatement object y BoundStatement object):
/* 
String queryText = "SELECT * FROM track_by_artist WHERE artist = '" + artist + "'";
ResultSet results = getSession().execute(queryText);
*/

// Preparamos consulta con string ? en los campos que obtendremos de variables 
   String queryText =  "SELECT * FROM track_by_artist WHERE artist =?";
   PreparedStatement prepared = getSession().prepare(queryText);
// Añadimos las variables  
   BoundStatement bound = prepared.bind(artist);
// Podemos realizar ya la consulta CQL
   ResultSet results = getSession().execute(bound);

Comprobamos que ya no se produce el error:


Ejercicio 6 - Realizando una petición por género

Necesitamos programa el método TracksDAO.listSongsByGenre() para añadir la funcionalidad de poder mostrar todas las canciones por género.

Primero será crear una nueva tabla en Cassandra (track_by_genre) para este tipo de consulta (de-normalización: crear nuevas tablas aunque suponga duplicar el almacenamiento de datos para poder ganar en velocidad).
cqlsh:playlist> CREATE TABLE track_by_genre (track_id UUID, genre TEXT, artist TEXT, track TEXT, track_length_in_seconds INT, music_file TEXT, PRIMARY KEY (genre,track,track_id))  ;
cqlsh:playlist> COPY track_by_genre  (track_id,genre,artist,track,track_length_in_seconds,music_file) FROM '/home/astwin/Escritorio/Cassandra/Leccion 2/scripts/songs.csv' WITH DELIMITER = '|' AND HEADER=true ;
59600 rows imported in 16.579 seconds.
Implementamos el método que se nos pide con la consulta adecuada por género (ver que la tabla nueva tiene como key primaria el genero, y no el artista):

 Comprobamos que ya obtenemos resultados en el apartado de búsqueda por genero:


Ejercicio 7 - Implementar 'introducir canción'

En el último apartado de la práctica se nos pide que introduzcamos una canción en la base de datos a través de la aplicación web y utilizando el modo de depuración de Eclipse comprobemos el proceso de añadir canción en el código de Java y completemos lo que pueda faltar.

Añadimos una canción utilizando la aplicación web (he añadido la canción Avicci - Hey Brother):
Comprobamos que se llama al método add() del objeto TracksDAO para insertar una nueva canción en la base de datos. Observamos como en este método sólo se implementan los comandos de insertar la nueva canción en las tablas artists_by_first_letter y track_by_artist, pero no lo hace en track_by_genre. Debemos completar este método. Importante recordar que en Cassandra se utiliza la filosofía de la denormalización, o implementar varias tablas para diversas consultas, aunque ello suponga  una redundancia en el almacenamiento de datos, y que esto implica tener que actualizar todas las tablas relacionadas ante la introducción de nuevos datos.

Comprobamos que se ha introducido correctamente y aparece en los tres tipos de consulta en la web:



jueves, 8 de mayo de 2014

Curso Datastax: Cassandra - Práctica 1

Instalar Java 7 

Descargamos e instalamos Java Standard Edition Development Kit (JDK):
http://www.oracle.com/technetwork/java/javase/downloads/index.html?ssSourceSiteId=ocomen

 sudo mkdir -p /usr/local/java  
 cd /home/astwin/Descargas/  
 sudo cp -r jdk-7u55-linux-x64.tar.gz /usr/local/java/ 
 cd /usr/local/java/ 
 sudo chmod a+x jdk-7u55-linux-x64.tar.gz  
 sudo tar xvzf jdk-7u55-linux-x64.tar.gz  

sudo gedit /etc/profile  
Añadimos al final del fichero profile:
JAVA_HOME=/usr/local/java/jdk1.7.0_55
PATH=$PATH:$HOME/bin:$JAVA_HOME/bin
export JAVA_HOME
export PATH
source /etc/profile  
sudo update-alternatives --install "/usr/bin/java" "java" "/usr/local/java/jdk1.7.0_55/bin/java" 1  
sudo update-alternatives --install "/usr/bin/javac" "javac" "/usr/local/java/jdk1.7.0_55/bin/javac" 1  
sudo update-alternatives --install "/usr/bin/javaws" "javaws" "/usr/local/java/jdk1.7.0_55/bin/javaws" 1  
sudo update-alternatives --set java /usr/local/java/jdk1.7.0_55/bin/java  
sudo update-alternatives --set javac /usr/local/java/jdk1.7.0_55/bin/javac  
sudo update-alternatives --set javaws /usr/local/java/jdk1.7.0_55/bin/javaws  
java -version  
 
java version "1.7.0_55"
Java(TM) SE Runtime Environment (build 1.7.0_55-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.55-b03, mixed mode)

Instalar Cassandra con Datastax community edition (DSC)

sudo gedit /etc/apt/sources.list.d/cassandra.sources.list 
Añadimos al fichero:
deb http://debian.datastax.com/community stable main
curl -L http://debian.datastax.com/repo_key | sudo apt-key add -
sudo apt-get update
sudo apt-get install dsc20


Comprobamos que la instalación es correcta: 
 
nodetool status 

Datacenter: datacenter1
=======================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
--  Address    Load       Owns (effective)  Host ID                               Token                                    Rack
UN  127.0.0.1  40,98 KB   100,0%            0549fd15-e907-4458-8610-4cd76934dfcb  -9181846608813468564                     rack1
Iniciamos el Shell de Cassandra y comprobamos el keyspace:

cqlsh  
Connected to Test Cluster at localhost:9160.
[cqlsh 4.1.1 | Cassandra 2.0.7 | CQL spec 3.1.1 | Thrift protocol 19.39.0] 
cqlsh> DESCRIBE KEYSPACES;
system  system_traces

Instalar Eclipse. Maven gestor de dependencias.

Ya tengo Maven instalado. Driver Java para programa cliente de Datastax: Link.
Para proyecto con Maven, utilizamos la siguiente dependencia: 
<dependency>
  <groupId>com.datastax.cassandra</groupId>
  <artifactId>cassandra-driver-core</artifactId>
  <version>2.0.2</version>
</dependency>

Primeros pasos con Cassandra

 
Creamos un keyspace llamado testks. Creamos una tabla llamada persona en ese keyspace que contiene el nombre, edad y horas que duerme una persona. Añadimos un registro a la tabla y realizamos una consulta a la tabla:
cqlsh> CREATE KEYSPACE testks WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };

cqlsh> DESCRIBE KEYSPACES;
system  testks  system_traces

cqlsh> USE testks ;

cqlsh:testks> CREATE TABLE persona(nombre text PRIMARY KEY, edad INT, horas_durmiendo FLOAT);

cqlsh:testks> INSERT INTO persona (nombre, edad , horas_durmiendo ) VALUES ( 'Jorge',5,13.2); 

cqlsh:testks> SELECT * FROM persona;
 nombre | edad | horas_durmiendo
--------+------+-----------------
  Jorge |    5 |            13.2

(1 rows)

Primer cliente de Cassandra utilizando el driver de Java  

Creamos un proyecto Maven, con las dependencias del driver de Cassandra. Implementamos un cliente simple que se conecta a la base de datos y realiza una consulta a la tabla que creamos anteriormente:

 

Comprobamos que se ejecuta correctamente:
 

 

Proyecto: Aplicación web de Playlist 

Abrimos el proyecto incluido en la práctica 1 con Eclipse y lo ejecutamos:
 

Abrimos la dirección http://localhost:8080/playlist/ para ver la aplicación web:
 


sábado, 3 de mayo de 2014

Estudio/Laboratorio - Aprendiendo SQL (con RDBMS MySQL) - Parte 3

SQL avanzado
 

Operadores 

Bloques con los que se construyen consultas complejas:
  • Operadores lógicos:
    Se reducen a aportar un resultado booleano true(1) o false(0).
    AND, &&       OR, ||      NOT,!
  • Operadores aritméticos:
    Suma: +   Resta: -  Multiplicación: *   División: /   Módulo: %
    El módulo es el resto de la división entera: 5%2=1   5=2*2+1
  • Operadores de comparación:
    Ver enlace: op. comparación.
    -   NULL=NULL --> NULL       NULL<=>NULL --> 1
    -   NULL=    0     --> NULL       NULL<=>    0     --> 0
    -   mysql> SELECT 4.5 BETWEEN 4 AND 5;       --> 1
    -   mysql> SELECT 5 BETWEEN 6 AND 4;          --> 0
    -   mysql> SELECT 'a' IN ('b','c','a');                     --> 1
    • Equivalencias de patrón con LIKE:
      Utilización de caracteres comodin como % (cualquier número de caracteres) o _ (cualquier carácter).
      - mysql> SELECT 'abcd' LIKE '%bc%';    -->  1
      - mysql> SELECT 'abcd' LIKE 'a___';      -->  1
      - mysql> SELECT 'abcd' LIKE '%a_';       -->  0
    • Expresiones regulares:
      Permiten realizar comparaciones muy potentes y complejas entre cadenas de caracteres.
      field REGEXP "^(https?://|www\\.)[\.A-Za-z0-9\-]+\\.[a-zA-Z]{2,4}"
      Patrón para discriminar urls como, www.google.il, http://google.com/,  http://ww.google.net/, www.google.com/index.php?test=data, https://yahoo.dk/as, http://goo.gle.com/,http://wt.a.x24-s.org/ye/, www.website.info
  • Operadores bit a bit: (suelen utilizarse muy poco)
     

Combinaciones avanzadas

Utilizamos las tablas creadas anteriormente:
 

 
  • Combinaciones internas
     
    • Se unen tablas con campos comunes en los que los registros coinciden en ambas.
      mysql> SELECT comercial, cliente, valor, nombre, apellido FROM ventas, comerciales WHERE codigo=1 AND ventas.comercial = comerciales.num_empleado;
      mysql> SELECT CONCAT(comerciales.nombre,' ',comerciales.apellido) as Comercial , valor, CONCAT(clientes.nombre,' ',clientes.apellido) AS Cliente FROM ventas, comerciales, clientes WHERE ventas.comercial = comerciales.num_empleado AND ventas.cliente = clientes.id ORDER BY valor;
    • Otra forma de realizarlo: INNER JOIN
      -  Las siguientes dos sentencias son equivalentes:
      mysql> SELECT comercial, cliente, valor, nombre, apellido FROM ventas INNER JOIN comerciales ON comercial=num_empleado WHERE codigo=1;
      mysql> SELECT comercial, cliente, valor, nombre, apellido FROM ventas, comerciales WHERE codigo=1 AND ventas.comercial = comerciales.num_empleado;
      - Un ejemplo utilizando dos inner join:
      mysql> SELECT CONCAT(comerciales.nombre,' ',comerciales.apellido) as Comercial , valor, CONCAT(clientes.nombre,' ',clientes.apellido) AS Cliente FROM ventas, comerciales, clientes WHERE ventas.comercial = comerciales.num_empleado AND ventas.cliente = clientes.id ORDER BY valor;
      mysql> SELECT CONCAT(comerciales.nombre,' ',comerciales.apellido) as Comercial , valor, CONCAT(clientes.nombre,' ',clientes.apellido) AS Cliente FROM comerciales INNER JOIN ( ventas INNER JOIN clientes on cliente = clientes.id) ON comercial = comerciales.num_empleado ORDER BY valor;
  • Combinaciones externas (por la izquierda o por la derecha)
    Añadimos una venta en la que el pago se ha realizado al contado, el cliente no está registrado en el sistema y no ha querido apuntarse (se introduce un NULL en el campo del cliente asociado a la tabla ventas):
    mysql> INSERT INTO ventas() VALUE (7,2,NULL,670)
    Display all 768 possibilities? (y or n)
    mysql> INSERT INTO ventas(codigo,comercial,cliente,valor) VALUE (7,2,NULL,670);
    mysql> SELECT * FORM ventas;
    Si ejecutamos la instrucción anterior que combinaba de forma interna las tres tablas, al no encontrarse el valor NULL de la tabla de ventas en la tabla de clientes, esa venta no se reflejará en la consulta. Se deben utilizar combinaciones externas.
    Una combinación externa devuelve todas las filas de la tabla de la izquierda o derecha (LEFT JOIN o RIGHT JOIN respectivamente), tengan o no coincidencia con las de la otra tabla. 
     mysql> SELECT CONCAT(comerciales.nombre,' ',comerciales.apellido) as Comercial , valor, CONCAT(clientes.nombre,' ',clientes.apellido) AS Cliente FROM ventas LEFT JOIN comerciales ON comercial=comerciales.num_empleado LEFT JOIN clientes ON cliente = clientes.id ORDER BY valor; 
  • Combinaciones externas completas
    Por ahora parece ser que MySQL no las soporta. Se pueden emular utilizando una unión de una selección completa por la izquierda y por la derecha.
  • Combinaciones naturales (NATURAL JOIN [USING])
    Cuando dos tablas tienen el mismo nombre para el campo por el que se quieren combinar se puede utilizar NATURAL JOIN.
    mysql> ALTER TABLE ventas CHANGE cliente id INT;
    mysql> SELECT nombre, apellido, valor FROM clientes NATURAL JOIN ventas;
    mysql> SELECT nombre, apellido, valor FROM ventas NATURAL LEFT JOIN clientes;
    Cuando dos tablas tienen más de un campo idénticos se puede utilizar la palabra clave USING para indicar los campos que deben ser coincidentes para la combinación. Añadimos un comercial a la tabla de clientes. Queremos saber cual de nuestros comerciales es a la vez un cliente; buscando sólo por apellido es ambiguo; buscamos por nombre y apellido, campos comunes en ambas tablas:
    mysql> INSERT INTO clientes VALUE (5,'Sol','Rive');
    mysql> SELECT id, clientes.nombre, clientes.apellido FROM clientes INNER JOIN comerciales ON apellido = comerciales.apellido ;
    ERROR 1052 (23000): Column 'apellido' in on clause is ambiguous
    mysql> SELECT id, clientes.nombre, clientes.apellido FROM clientes INNER JOIN comerciales USING (apellido,nombre) ;
    mysql> DELETE FROM clientes WHERE id=5; 
  • Datos que aparecen en una tabla pero no en otra.
    Se han visto como recuperar registros que aparecen en dos tablas, o también todos los registros que aparecen en una tabla y que pueden estar o no en otra. Otra posibilidad es la de obtener solamente los resultados que se encuentran en una pero en la otra no.
    Podemos realizar una combinación externa filtrando los resultados en los que exista NULL para obtener los registros que se encuentran en una tabla, pero en otra no.  Insertamos un nuevo comercial; éste no ha realizado ninguna venta.
    mysql> INSERT INTO comerciales VALUES (5,'Jomo','Ignesund',10,'22-11-29','1968-12-01');
    mysql> SELECT nombre,apellido,comercial FROM comerciales LEFT JOIN ventas ON num_empleado = ventas.comercial;
     mysql> SELECT nombre,apellido FROM comerciales LEFT JOIN ventas ON num_empleado = comercial WHERE comercial IS NULL;
    Con la combinación externa se buscan todos los comerciales existentes y sus ventas, y si no las tienen también se incluyen, pero el campo de unión será NULL. Aprovechando esto, se realiza un filtrado con WHERE y IS NULL.  
  • Combinación de resultados (UNION)
    Combina los resultados de diferentes instrucciones SELECT, cada una de ellas debe constar con el mismo numero de columnas. Devuelve resultados únicos (como si se aplicara DISTINCT). Se utiliza UNION ALL para obtener todos los resultados, duplicados incluidos:
    Creamos una nueva tabla con clientes_antiguos y unimos una petición de las tabla de clientes con ella:
    mysql> CREATE TABLE clientes_ant(id INT, nombre VARCHAR(30), apellido VARCHAR(40));
    mysql> CREATE TABLE clientes_ant(id INT, nombre VARCHAR(30), apellido VARCHAR(40));
    mysql> SELECT id,nombre,apellido FROM clientes UNION SELECT id,nombre,apellido FROM clientes_ant;
    Podemos ordenar la consulta completa con ORDER BY al final. Si se desea sólo una de las consultas individuales ordenadas se deben utilizar paréntesis:
    mysql> SELECT id,nombre,apellido FROM clientes UNION SELECT id,nombre,apellido FROM clientes_ant ORDER BY apellido,nombre;
    mysql> SELECT id,nombre,apellido FROM clientes UNION (SELECT id,nombre,apellido FROM clientes_ant ORDER BY apellido,nombre);
    Diferencias entre UNION y UNION ALL:
    mysql> SELECT id FROM clientes UNION SELECT id FROM ventas;   --> 5 resultados (1,2,3,4,NULL), sólo id distintas.
    mysql> SELECT id FROM clientes UNION ALL SELECT id FROM ventas;  --> 11 resultados (1,2,3,4,1,3,3,...). Ambas columnas completas.
  • Subselecciones
    Realizar una selección dentro de otra operación de selección:
    mysql> SELECT nombre, apellido FROM comerciales WHERE num_empleado IN (SELECT codigo FROM ventas WHERE valor>1000);
    Es lo mismo que una combinación interna, que resultan ser más eficientes para realizar consultas y los resultados se recuperan con mayor rapidez:
    mysql> SELECT DISTINCT nombre,apellido,valor FROM comerciales INNER JOIN ventas ON num_empleado = ventas.comercial WHERE valor>1000;
    O también:
    mysql> SELECT DISTINCT nombre,apellido,valor FROM comerciales,ventas WHERE comerciales.num_empleado = ventas.comercial AND valor>1000;

Como agregar registros a una tabla desde otras tablas con INSERT SELECT

La instrucción INSERT también permite agregar registros a una tabla desde otras. Por ejemplo, queremos una nueva tabla que contenga los clientes y el valor de todas las comprar realizadas:
mysql> SELECT nombre,apellido,sum(valor) FROM ventas NATURAL JOIN clientes GROUP BY nombre,apellido;
Creamos tabla que reciba los resultados:
mysql> CREATE TABLE clientes_compras_tot(nombre VARCHAR(30),apellido VARCHAR(40), compras_totales INT) ;
mysql> INSERT INTO clientes_compras_tot(nombre,apellido,compras_totales) SELECT nombre,apellido,sum(valor) FROM ventas NATURAL JOIN clientes GROUP BY nombre,apellido;
 mysql> SELECT * FROM clientes_compras_tot;

Mas sobre la agregación de registros

  • SELECT permite una sintaxis similar a instrucción UPDATE:
    mysql> INSERT INTO clientes_compras_tot(nombre, apellido, compras_totales) VALUES ('Charles','Dube',0);
    Equivale a:
    mysql> INSERT INTO clientes_compras_tot SET nombre='Charles', apellido='Dube', compras_totales=0;
  • Se puede llevar a cabo una forma limitada de cálculo al agregar registros:
    mysql> ALTER TABLE clientes_compras_tot ADD value2 INT;
    mysql> INSERT INTO clientes_compras_tot VALUES ('Gladis','Malherbe',5,compras_totales*2)

Mas sobre como eliminar registros (DELETE y TRUNCATE)

Se pueden eliminar todos los registros de una tabla con una instrucción DELETE sin utilizar ningún filtro con WHERE:
mysql> DELETE FROM clientes_compras_tot;
La mejor forma y más rápida de realizarlo es mediante TRUNCATE:
mysql> TRUNCATE clientes_compras_tot;  

Variables de usuario (SET ó SELECT  @_:=)

SQL consta de funciones que le permiten almacenar valores como variables temporales. Es habitual utilizar un lenguaje de programación para realizar este tipo de acciones, pero también pueden resultar útiles cuando se trabaja en la linea de comandos:
mysql> SELECT @avg := AVG(comision) FROM comerciales;
mysql> SELECT @avg;
mysql> SELECT nombre,apellido FROM comerciales WHERE comision>@avg;
Podemos asignar una variable de forma específica con SET:
mysql> SET @resultado=22/7;
mysql> SELECT @resultado;
Las variables de usuario se establecen en un subproceso dado y ningún otro proceso puede acceder a ellas. Al cerrar el proceso o perder la conexión las variables dejan de estar asignadas.

SQL y archivos  

  • Modo de procesamiento por lotes
Guardamos en un archivo llamado test_archivo.sql las siguientes lineas para incluir dos clientes:
INSERT INTO clientes(id,nombre,apellido) VALUES (5,'Francouis','Papo')
INSERT INTO clientes(id,nombre,apellido) VALUES (6,'Neil','Benteke')
Podemos ejecutar estás líneas desde la linea de comandos del sistema operativo:
mysql practiceDB < test_archivo.sql
Si algunas de las líneas del archivo contiene algún error, mySQL interrumpirá el procesamiento del archivo. Para seguir procesando el resto del archivo aunque alguna de las líneas sea errónea se debe utilizar la opción force (-f): 
mysql -f practiceDB < test_archivo.sql 
  • Usar archivo de procesamiento por lotes desde la terminar MySQL 
    Desde la terminar de MySQL se puede ejecutar los comandos almacenados en un archivo utilizando el comando SOURCE:
    mysql> SOURCE test_archivo.sql
  •  Redireccionamiento de la salida hacia un archivo
     

    Modificamos el archivo test_archivo.sql:
    DELETE FROM clientes WHERE id>=5;
    INSERT INTO clientes(id,nombre,apellido) VALUES (5,'Francouis','Papo');
    INSERT INTO clientes(id,nombre,apellido) VALUES (6,'Neil','Benteke');
    SELECT * FROM clientes;
    Borra las entradas que hemos puesto, las vuelve a añadir y realizamos una petición para ver la tabla completa que hemos modificado. Redirigimos la salida estandar hacia un archivo:
    mysql practiceDB < test_archivo.sql > test_salida.txt
    Si abrimos el archivo test_salida.txt podemos observar que se ha guardado la tabla clientes, utilizando una tabulación (\t) para separar campos.
    Podemos activar el formato interactivo (el mismo que se muestra en la terminar de MySQL) en el archivo de salida con la opción -t:
    mysql -t practiceDB < test_archivo.sql > test_salida.txt

Transacciones y bloqueos

 

viernes, 2 de mayo de 2014

Estudio/Laboratorio - Aprendiendo SQL (con RDBMS MySQL) - Parte 2

Tipos de datos y tipos de tablas

Tipos de columna

Existen tres tipos fundamentales de columnas en MySQL: numéricas, de cadena de caracteres y de fecha. Se debe seleccionar el tipo de columna de menor tamaño que sea capaz de abarcar el rango completo de los datos que se pretenden almacenar.

Numéricos:

TINYINT,BIT,BOOL,SMALLINT,MEDIUMINT,INT,BIGINT,FLOAT,DOUBLE,REAL,DECIMAL,DEC,NUMERIC.
- Dos tipos principales: enteros y de coma flotante.
- Todos permiten dos opciones:
  • UNSIGNED: no se permite el uso de números negativos.
  • ZEROFILL: sin signo y se rellena con ceros (1 ->001).

De cadena de caracteres: 

CHAR(n), VARCHAR(n), TINYBLOB, TINYTEXT, BLOB, TEXT, MEDIUMBLOB, MEDIUMTEXT, LONGBLOB, LONGTEXT, ENUM('valor 1',...), SET('valor 1',...)
- En tipo BLOB la búsqueda discrimina entre mayúsculas y minúsculas, en TEXT no.
- Un campo ENUM sólo puede tomar un valor de entre unas cuantas cadenas de texto. Define una variable categórica.
- Un campo SET puede tomar un conjunto de valores, todos pertenecientes a las cadenas de texto introducidas.

De fecha:

DATETIME, DATE, TIMESTAMP, TIMESTAMP(n), TIME, YEAR

Distintos tipos de tablas

Tablas MyISAM

  • Tipo predeterminado. Ideal para sistemas en los que se realizan una gran cantidad de consultas de actualización.
  • Almacenadas en un directorio: archivo de datos con extensión .MYD y archivo de índices con extensión .MYI.
  • Tres subtipos:

Tablas estáticas

Todas las columnas de longitud fija, muy rápidas, sencillas de reconstruir tras un fallo, no se necesitan reorganizar, pero requieren de mayor espacio en el disco.

Tablas dinámicas

Algunas columnas son de longitud variable. Se ahorra espacio, pero su manejo es más complejo y resultaran más lentas, requieren mantenimiento regular para evitar la fragmentación, no resultan tan sencillas de reconstruir tras un fallo.

Tablas comprimidas

Tablas de sólo lectura. Se crean con la utilizad myisampak. Cada columna comprimida de forma separada. 

Tablas MERGE

Son la fusión de dos tablas MyIsam iguales. Se utilizan cuando las tablas MyIsam empiezan a resultar demasiado grandes.

Tablas HEAP

Se almacenan en memoria, por lo que son muy rápidas. Se suelen utilizar para acceder rápidamente a una tabla ya existente, dejando la original para labores de inserción y actualización.

Tablas InnoDB

InnoDG: Garantizan la seguridad en las transacciones, lo que permite la agrupacion de instrucciones para asegurar la integridad de los datos. Dispone de las funciones COMMIT Y ROLLBACK para realizar transacciones. Se aconsejan cuando se necesitan realizar una gran cantidad de operaciones de inserción y actualización

Tablas DBD 

 Garantizan la seguridad en las transacciones.

 

Estudio/Laboratorio - Aprendiendo SQL (con RDBMS MySQL) - Parte 1

Instalando MySQL y creando mi primera base de datos

 
Instalando mySQL en ubuntu 12.04:
sudo apt-get install mysql-server
Durante la instalación te pedirá que introduzcas un password para la cuenta raíz (root). Iniciamos el terminal de mysql con usuario root (-uroot) con su correspondiente password (-p****):
mysql -uroot -p*****
Creo una base de datos para practicar llamada practiceDB y le concedo permisos completos de accesos a mi usuario habitual en ubuntu (acceso sin password):
mysql> CREATE DATABASE practiceDB;
mysql> GRANT ALL ON practiceDB.* TO astwin@localhost IDENTIFIED BY '';
Ahora ya puedo acceder a la base de datos practiceDB de una forma sencilla:
mysql practiceDB

Creación de tablas (CREATE)


Crear tabla:
mysql> CREATE TABLE comerciales(num_empleado INT, apellido VARCHAR(40),nombre VARCHAR(30), comision TINYINT);
Ver tablas:
mysql> SHOW TABLES;
Análisis de estructura de tabla:
mysql> DESCRIBE comerciales;  

Inserción de registros en tablas (INSERT)

 
Insertar registro a registro:
mysql> INSERT INTO comerciales(num_empleado,apellido,nombre,comision) VALUES (1,'Rive','Sol',10);
mysql> INSERT INTO comerciales(num_empleado,apellido,nombre,comision) VALUES (2,'Gordimer','Charlene',15);
mysql> INSERT INTO comerciales(num_empleado,apellido,nombre,comision) VALUES (3,'Serote','Mike',10);
mysql> select * from comerciales;
mysql> TRUNCATE comerciales;
Insertar de forma más sencilla siguiendo el orden de definición de campos:
mysql> INSERT INTO comerciales VALUES (1,'Rive','Sol',10);
mysql> INSERT INTO comerciales VALUES (2,'Gordimer','Charlene',15);
mysql> INSERT INTO comerciales VALUES (3,'Serote','Mike',10);
mysql> select * from comerciales;
mysql> TRUNCATE comerciales;
Insertar múltiples registros:
mysql> INSERT INTO comerciales(num_empleado,apellido,nombre,comision) VALUES (1,'Rive','Sol',10),(2,'Gordimer','Charlene',15),(3,'Serote','Mike',10); mysql> TRUNCATE comerciales;

Insertar registros desde archivos de texto:
Para habilitar a mySQL a leer archivos locales se necesita tener activada la propiedad  --local-infile=1 (por defecto a 0). En este caso abrimos una sesión con esta propiedad:  mysql practiceDB --local-infile
mysql> LOAD DATA LOCAL INFILE 'tabla_comerciales.txt' INTO TABLE comerciales FIELDS TERMINATED BY ',';
Archivo 'tabla_comerciales.txt'
1,Rive,Sol,10
2,Gordimer,Charlene,15
3,Serote,Mike,10

Recuperación de información en una tabla (SELECT)

 
Comando SELECT, WHERE  y clausulas condicionales:
mysql> SELECT * FROM comerciales;
mysql> SELECT nombre FROM comerciales;
mysql> SELECT nombre,apellido FROM comerciales;
mysql> SELECT num_empleado,nombre,apellido FROM comerciales WHERE apellido='Gordimer';
mysql> SELECT * FROM comerciales WHERE comision > 11 OR apellido='Rive' AND nombre='Sol' ;
mysql> SELECT * FROM comerciales WHERE (comision > 11) OR (apellido='Rive' AND nombre='Sol');
mysql> SELECT * FROM comerciales WHERE (apellido='Rive') OR (apellido='Rive' AND comision>11);
Correspondencia de patrones (instrucción LIKE):
mysql> SELECT * FROM comerciales WHERE apellido LIKE 'Sero%';
mysql> SELECT * FROM comerciales WHERE apellido LIKE '%e%';
mysql> SELECT * FROM comerciales WHERE apellido LIKE 'e%';
mysql> SELECT * FROM comerciales WHERE apellido LIKE '%e%e'; 
Ordenación de los resultados (clausula ORDER BY):
mysql> INSERT INTO comerciales VALUES (4,'Rive','Mongane',10),(5,'Smith','Mike',12);              
mysql> SELECT * FROM comerciales ORDER BY apellido;
mysql> SELECT * FROM comerciales ORDER BY apellido,nombre;
mysql> SELECT * FROM comerciales ORDER BY comision DESC;
mysql> SELECT * FROM comerciales ORDER BY comision DESC, apellido ASC, nombre ASC; 
Limitación del número de resultados (clausula LIMIT):
mysql> SELECT nombre , apellido , comision FROM comerciales ORDER BY comision DESC LIMIT 1;
mysql> SELECT nombre , apellido , comision FROM comerciales ORDER BY comision DESC LIMIT 0,1;
mysql> SELECT nombre , apellido , comision FROM comerciales ORDER BY comision DESC LIMIT 1,1; 
Utilización de funciones para ajustar las consultas ( SUM(),AVG(),MIN(),MAX() ):
mysql> SELECT MAX(comision) FROM comerciales;
mysql> SELECT AVG(comision) FROM comerciales;
mysql> SELECT MIN(comision) FROM comerciales;
mysql> SELECT SUM(comision) FROM comerciales; 
Recuperación de los resultados con registros únicos (clausula DISTINCT):
mysql> SELECT DISTINCT apellido FROM comerciales ORDER BY apellido;
Contar el número de resultados obtenidos (clausula COUNT):
mysql> SELECT COUNT(*) FROM comerciales;
mysql> SELECT COUNT(*) FROM comerciales WHERE comision > 10;
mysql> SELECT COUNT(*) FROM comerciales WHERE comision >= 10;
mysql> SELECT COUNT(DISTINCT apellido) FROM comerciales;
mysql> SELECT COUNT(DISTINCT apellido) FROM comerciales WHERE comision=10;
Cálculos en consultas:
mysql> SELECT nombre, apellido, comision + 5 FROM comerciales;

Eliminación de registros (DELETE)

mysql> DELETE FROM comerciales WHERE num_empleado = 5;

Cambiar registros de una tabla (UPDATE)

mysql> UPDATE comerciales SET comision = 12 WHERE num_empleado = 1 ;
mysql> UPDATE comerciales SET comision = 12 WHERE comision = 10 ;
mysql> UPDATE comerciales SET comision = 10 WHERE comision = 12 ;

Eliminación de tablas y bases de datos (DROP)

mysql> CREATE TABLE comision (id INT);
mysql> SHOW TABLES;
mysql> DROP TABLE comision ;
mysql> SHOW TABLES;
Desde la cuenta de root:      mysql -uroot -p****      
mysql> CREATE DATABASE aux;
mysql> SHOW DATABASES;
mysql> DROP DATABASE aux;
mysql> SHOW DATABASES;

Modificar estructura de la tabla (ALTER TABLE)

 
Agregar columna (ADD):
mysql> ALTER TABLE comerciales ADD fecha_incor DATE;
mysql> DESCRIBE comerciales;
mysql> ALTER TABLE comerciales ADD año_nacimiento YEAR;
mysql> DESCRIBE comerciales;
Modificar definición de una columna (CHANGE o MODIFY):
mysql> ALTER TABLE comerciales CHANGE año_nacimiento cumple DATE;
mysql> ALTER TABLE comerciales CHANGE cumple cumpleaños DATE;
mysql> ALTER TABLE comerciales MODIFY cumpleaños YEAR;
mysql> ALTER TABLE comerciales MODIFY cumpleaños DATE; 
Cambiar nombre de tabla (RENAME):
mysql> ALTER TABLE comerciales RENAME agentes_ventas;
mysql> DESCRIBE agentes_ventas;
mysql> ALTER TABLE agentes_ventas RENAME comerciales;
Eliminar columna (DROP):
mysql> ALTER TABLE comerciales ADD aux INT;
mysql> DESCRIBE comerciales;
mysql> ALTER TABLE comerciales DROP aux;
mysql> DESCRIBE comerciales;

Funciones de fecha

 
Formato de la fecha ( DATE_FORMAT() ):
mysql> SELECT DATE_FORMAT(fecha_incor,'%d/%m/%Y') FROM comerciales WHERE num_empleado = 1; 
Fecha y hora actual ( CURRENT_DATA()  NOW() ):
mysql> SELECT NOW(), CURRENT_DATE();
Funciones de fecha YEAR(), MONTH(), DAYOFMONTH():
mysql> SELECT YEAR(cumpleaños),MONTH(cumpleaños), DAYOFMONTH(cumpleaños) FROM comerciales;
Operaciones con fechas:
Intentamos obtener la edad restando el año de la fecha actual a el año del nacimiento, pero así no se tiene en cuenta la fecha de verdad (puedes estar en abril y hasta septiembre no tener la edad). Hay que tener también en cuenta el dia y mes:
mysql> SELECT YEAR(NOW())-YEAR(cumpleaños) FROM comerciales;
mysql> SELECT RIGHT(CURRENT_DATE(),5) < RIGHT(cumpleaños,5) FROM comerciales;
mysql> SELECT nombre, apellido, YEAR(NOW())-YEAR(cumpleaños)- ( RIGHT(CURRENT_DATE(),5) < RIGHT(cumpleaños,5) ) AS edad FROM comerciales;

Consultas más avanzadas

Renombrar campo al realizar una consulta (operador AS):
mysql> SELECT apellido ,nombre, MONTH(cumpleaños) AS mes, DAYOFMONTH(cumpleaños) AS dia FROM comerciales ORDER BY mes;

Combinación de columnas (CONCAT):
mysql> SELECT CONCAT(nombre,' ',apellido) as nombre_completo,  MONTH(cumpleaños) AS mes, DAYOFMONTH(cumpleaños) AS dia FROM comerciales ORDER BY mes; 
Creamos dos tablas más: 
Tabla_ventas.txt 
1,1,1,2000
2,4,3,250
3,2,3,500
4,1,4,450
5,3,1,3800
6,1,2,500
Tabla_clientes.txt
1,Yvonne,Clegg
2,Johnny,Chaka
3,Winston,Powers
4,Patricia,Mankunku
mysql> CREATE TABLE clientes(id INT,nombre VARCHAR(30), apellido VARCHAR(40));
mysql> CREATE TABLE ventas(codigo INT,comercial INT, cliente INT, valor INT);
mysql> LOAD DATA LOCAL INFILE 'tabla_clientes.txt' INTO TABLE clientes FIELDS TERMINATED BY ',';
mysql> LOAD DATA LOCAL INFILE 'tabla_ventas.txt' INTO TABLE ventas FIELDS TERMINATED BY ',';
Combinación de varias tablas (se unen por las instancias comunes de cada una):
mysql> SELECT comercial,cliente,valor,nombre,apellido FROM ventas,comerciales WHERE codigo=1 and comerciales.num_empleado=ventas.comercial;
mysql> SELECT codigo,cliente,valor FROM comerciales, ventas WHERE nombre='Sol' AND apellido ='Rive' AND ventas.comercial=comerciales.num_empleado;
mysql> SELECT codigo,cliente,valor FROM comerciales, ventas WHERE nombre='Sol' AND apellido ='Rive' AND comercial=num_empleado ;

Agrupación de una consulta  (GROUP BY)

mysql> SELECT comercial,SUM(valor) FROM ventas GROUP BY comercial;
mysql> SELECT comercial,SUM(valor) AS total_ventas, COUNT(*) as num_ventas FROM ventas GROUP BY comercial ORDER BY total_ventas DESC;
mysql> SELECT nombre,apellido,comercial,COUNT(*) as num_ventas FROM ventas,comerciales WHERE ventas.comercial=comerciales.num_empleado GROUP BY comercial;

miércoles, 23 de abril de 2014

Laboratorio: Sistema de Recomendación con Mahout

Tutorial de creación de sistema de Recomendación

   En la pagina web de Apache Mahout se proporciona un pequeño tutorial de cómo crear un sistema de recomendación (filtrado colaborativo entre usuarios):

https://mahout.apache.org/users/recommender/userbased-5-minutes.html

Pasos seguidos: 
  1. Integración de Eclipse con Maven.
  2. Creación de un Proyecto Maven.
  3. Añadir dependencias en "pom.xml". En mi caso tengo instalado la versión de mahout de la distribución CDH5 de cloudera.
        <dependency>                                                  
            <groupId>org.apache.mahout</groupId> 
            <artifactId>mahout-core</artifactId>          
            <version>0.8-cdh5.0.0</version>              
        </dependency>                                                 
     
     
Recomendación de 3 items al usuario 2
Evaluación del sistema de recomendación











Aplicación del sistema de recomendación en un dataset real

   El grupo de investigación GroupLense proporciona a través de su pagina web diversos datasets de puntuaciones de películas proporcionadas por diferentes usuarios extraídos de la página MovieLens. He utilizado el dataset MovieLens 1M, que proporciona 1 millón de puntuaciones proporcionadas por 6000 usuarios sobre 4000 películas.

Ejemplo de recomendación de películas.


lunes, 14 de abril de 2014

Estudio: Aplicaciones de la minería de datos con R


   He leído el libro "Data Mining Applications with R", Editors: Yanchang Zhao, Yonghua Cen, Elsevier, December 2013, ISBN: 978-0-12-411511-8, 514 pages.
 
   En él se presentan 15 proyectos reales donde se han utilizado técnicas de minería de datos utilizando la herramienta R. Me ha parecido muy interesante, siendo de gran ayuda para descubrir nuevas técnicas y paquetes R relacionados con la minería de datos, siendo utilizadas en la resolución de problemas de análisis reales.
 

1 - Power Grid Data Analysis with R and Hadoop.

   Análisis de series temporales de datos (big data) proporcionados por sensores (PMU) en la red eléctrica (aprox. 2TB, 53 millones registros generados por una red de sensores distribuidos).
  Se utilizan técnicas de análisis exploratorio (proceso interactivo e iterativo, involucrando limpieza de datos, y diferentes análisis estadísticos y visualizaciones de datos) en grandes cantidades de datos mediante la integración de R con Hadoop, para identificar diferentes patrones de pérdida de la sincronización en frecuencia (en la red eléctrica, la frecuencia de la señal debe ser la misma, independientemente del lugar donde se mida).
  Se realiza una interesante introducción a diferentes paquetes relacionados con la computación de altas prestaciones (High-Performance Computing, HPC), y se centra en el uso del paquete RHIPE para integrar R y Hadoop:
- Computación paralela multicore: parallel (integra snow y multicore). Aplicaciones que requieren gran capacidad de procesado, pero no recomendables para grandes cantidades de datos. 
- Trabajar con grandes datos fuera de la memoria de R: paquetes ff, bigmemory y RevoScaleR, especializados en trabajar con matrices o data frames con grandes cantidades de filas. 
- Procesado distribuido integrando R con Hadoop: paquetes rmr (utiliza el esquema de streaming de Hadoop) y RHIPE (integrado con la API de Java de Hadoop).

2 - Picturing Bayesian Classifiers: A Visual Data Mining Approach to Parameters Optimization.

   Es razonable pensar que existe un proceso oculto que modela y explica los datos que obtenemos en un problema. Generalmente no conocemos este proceso, pero sabemos que no es completamente aleatorio, lo que nos permite encontrar una buena y útil aproximación mediante algún modelo matemático conocido, el cuál se puede adaptar a diferentes comportamiento de los datos dependiendo del valor de varios parámetros:
- En el área de machine learning, se utilizan computadores programados para obtener el valor de estos parámetros, de forma que se optimice algún determinado criterio de rendimiento. 
- En la minería de datos visual se intenta involucrar al ser humano para explotar sus habilidades perceptivas en el proceso de exploración y selección de parámetros. 
   En este trabajo se implementa un GUI para que un usuario pueda visualizar el proceso de entrenamiento de un clasificador basado en Naive Bayes (clasificador probabilístico empleando el criterio bayesiano, en donde se asume independencia entre las variables para simplificar el modelo) y poder interactuar con él para mejorar las prestaciónes de clasificación. Se realiza una introducción teórica al clasificador y se introducen las distribuciones multivariantes de Bernuilli, multinomial y de Poisson como posibilidades para construir el modelo. Posteriormente se describe un modo gráfico para visualizar el proceso y resultados de la clasificación, que permite implementar una GUI donde el usuario puede utilizar para el diseño y verificación del clasificador.
   Se introducen diferentes paquetes para poder construir GUIs o plots interactivos como son RGGobi  o RStudio (fuerza a utilizar el IDE Rstudio). Se utilizan finalmente los paquetes gWidgets (API para crear GUIs interactivas), gWidgetsRGtl2 (usar las librerias de GIMP Toolkit con gWidgets), cairoDevice (insertar plot de R en una GUI GIMP) y ggplot2.

3 - Discovery of emergent issues and controversies in Anthropology using text mining, topic modeling and social network analysis of microblog content.

   En esta aplicación se propone el uso de R para realizar labores de minería de texto,  análisis de contenidos y análisis de redes sociales en Twitter. Se estudia un hastag asociado con una reunión de la Asociación Americana de Antropología (AAA). Estudio de cuantos usuarios intervienen, estadísticas de tweets (tweets, retweets, menciones, otros hastags asociados), usuarios más influyentes (más retwitteados, más mencionado), la estructura de la comunidad que interviene (cómo están conectados los usuarios que intervienen en el hastag entre sí), análisis de contenido (analisis de asociación de términos, análisis de sentimientos, modelado de temas).

4 - Text Mining and Network Analysis of Digital Libraries in R.

   Otra aplicación de minería de texto, en este caso orientada hacia el estudio de una librería digital. Cinco pasos en el análisis:
- Preparación del conjunto de datos: uso de paqute tm para el procesado orientado al texto incluido en los diferentes documentos: quitar carácteres indeseados, puntuación, palabras sin valor...
- Exploración de matriz de términos en los documentos: relación entre documentos y términos.
- Análisis de temas y clustering de contenidos usando Latent Dirichlet Allocation, LDA: paquete lda, modelo que considera que cada documento se basa en una mezcla de tópicos o temas.
- Cohesión o clústering de documentos.
- Análisis de la red social entre los autores: paquetes igraph para construcción de grafos y sna para realización de mediciones en la red.

5 - Recommendation systems in R.

   En un sistema de recomendación se asocia determinados tipos de productos, items o servicios con determinado tipos de usuarios. Se busca ofrecer al usuario nuevos productos, items o servicios más acordes a sus preferencias o comportamientos.
  Se utiliza el paquete recommenderlab para la construcción de sistemas de recomendación (en este caso de películas, basado en la puntuación de los usuarios en MovieLense). Inicialmente se introducen diferentes medidas utilizadas en la evaluación de estos sistemas (error cuadrático medio, precision/recall/f-value/AUC, hit rate, serendipity...). Posteriormente se centra en los diferentes modelos que se pueden construir con el paquete anteriormente mencionado: selección aleatoria, items más populares y modelos basados en el filtrado colaborativo:
- Atendiendo al tipo de usuarios UBCF o atendiendo al tipo de item IBCF.
- Atendiendo a factores latentes (donde se utilizan técnicas SVD o PCA para simplificar el problema).
- Filtrado basado en contenido.
- Binarización de datos + reglas de asociación.

6 - Response Modeling in Direct Marketing: A Data Mining Based Approach for Target Selection.

   Las empresas tradicionalmente han utilizado promociones de sus productos a gran escala (marketing masivo), proporcionando a todos los clientes las mismas ofertas y productos. En este tipo de estrategia no se tiene en cuenta las diferencias entre clientes. Otro tipo de estrategia es la llevada a cado en el marketing directo, donde se pretende establecer una relación directa con los clientes y proporcionarles ofertas de productos o servicios específicos acordes con lo que se estima que puede resultarles más interesantes. Utilizando datos históricos de compras y datos demográficos entre otros, se utilizan técnicas de data mining y modelado predictivo para generar modelos de clientes a los que les puede interesar un cierto producto o servicio.
   Esta aplicación se basa en la creación de un modelo de respuesta para predecir la probabilidad de que un determinado cliente pueda verse atraido por una nueva promoción u oferta. El modelo de respuesta se formula como un problema de clasificación binaria (un detector), dividiendo los clientes en dos clases, clientes interesados y no interesados. El modelo de respuesta propuesto consite en diferentes pasos: recolección de datos, preprocesado, extracción de características,  selección de características, balanceado entre clases, clasificación y evalucación. Se aplica utilizando datos de un banco privado Iraní: utilizando diferentes variables RFM (recency, frequency, monetary) que indican el comportamiento en las compras de los clientes, y diferente información demográfica. Se utilizan 85 variables primarias.
   Se construyen variables secundarias mediante la multiplicación de todas las posibles parejas. Utilizando la medida F-score (sencilla medida para medir la discriminación entre dos set de numeros reales) se escogen las 20 medidas secundarias que presentan mayor discriminación. De las 105 variables (85 directas+20 secundarias) se escogen solamente 50 utilizando la misma medida de F-score. Utilizando una técnica de selección de características basada en Random Forest (paquetes randomForest y varSelRF) se seleccionan las 26 mejores variables y se realiza un balanceado entre clases (basado en un submuestreo de la clase de clientes no interesados).  Se entrena un clasificador SVM (paquete e1071) con kernell RBF y una técnica de "grid-search" con validación cruzada (5 validaciones) para escoger el valor de los parámetros C y gamma del clasificador.

7 - Caravan Insurance Policy Customer Profile Modeling with R Mining.

   Se presenta otra aplicación de modelado de la respuesta de los clientes, en este caso en una empresa de seguros de caravanas. En este caso se utilizan cuatro técnicas diferentes en la implementanción del clasificador binario: recursive Partitioning (paquetes rpart y caret), Bagging Ensemble (libreria ipred), SVM y clasificador basado en regresión lineal.

8 - Selecting Best Features for Predicting Bank Loan Default.

   Una aplicación donde se habla de técnicas de selección de características en la predicción de inclumplimiento de préstamos bancarios. En esta aplicación se implementa otro sistema de detección (clasificación binaria). Se comentan los pasos de extracción de datos, exploración y limpieza, detección de elementos nulos: paquete VIM, detección de outliers: técnica boxplot y clustering paquete cluster, normalización, balanceado de datos: método SMOTE paquete DMwR, selección de características usando Random Forest  y clasificación mediante árbol de decisión.

9 - A Choquet Integral Toolbox and its Application in Customer's Preference Analysis.

   Actualmente, la identificación de las preferencias de los clientes es esencial para tareas de producción y marketing en la administración de empresas. La toma de decisiones basada en datos de clientes involucra la comparación de diversas alternativas, las cuales son evaluadas siguiendo varios factores relativos a las prioridades de los clientes (multicriteria decision making, MCDM). En este caso se utiliza el método Choquet Integral para la agregación de fuzzy meassures para asignar importancia a todos los posibles grupos de criterios para modelar un proceso MCDM.
   Inicialmente se presenta la teoría y  se introduce un sencillo ejemplo  para ilustrar la utilización del paquete Rfmtool. Posteriormente se demuestra el uso del método basado en Choquet integral de agregación de fuzzy meassures para descubrir las preferencias de los viejeros en la selección de los hoteles utilizando datos extraidos de tripadvisor.com.

10 - A Real-Time Property Value Index based on Web Data.

   Se presenta una metodología para obtener estimadores fiables del nivel del precio de la vivienda en una determinada área.  Se obtienene los datos del precio de la vivienda en Bilbao utilizando los anunciós publicados por particulares en el portal www.idealista.com. No se especifica el proceso completo de captura de datos, pero se nos proporciona detalles de como se ha realizado: cada oferta subida por un usuario se encuentra en una URL, la cual es descargada a un archivo FILE y después se analiza su código HTML utilizando el paquete XML:
 download.file(URL,File,quiet=0, method="get")  ...
 doc <- htmlTreeParse(file=FILE)$children$html[["body"]]   ...
   Se realiza geocoding, obteniendo datos de las coordenadas geográficas a partir de las direcciones de las viviendas. Se introduce la API de Google maps en paquete ggmap para la realización de geocoding, y los paquetes maptools, rgdal, RgoogleMaps y sp para acceder a la cartografía, dibujar mapas y superponer polígonos o puntos en un mapa para descubrir patrones.
   Se entrenan modelos de regresión hedónica para medir el efecto del tiempo en el precio de venta de las viviendas. Paquetes gam, mgcv. 

11 - Predicting Seabed Hardness Using Random Forest in R.

   Se implementa un sistema de predicción de la dureza del suelo marino utilizando 15 variables relacionadas con la barimetría y backscatter. Se implementa un sistema de detección o clasificación binaria, categorizando el sustrato en hard o soft. Se utiliza un modelo basado en Random Forest.

12 - Supervised classification of images, applied to plankton samples using R and zooimage.

   En este caso se implementa un sistema de clasificación basado en imágenes. Se entrena un sistema de clasificación de muestras de plancton. Se utilizan los paquetes zooimage y mlearning, los cuales proporcionan diferentes funciones que ayudan en el trabajo de la adquisición y análisis de las imágenes, el procesado de metadatos, la elaboración de datasets para training/test y el procesado final de los datos. En el estudio se testean dos clasificadores binarios: Random Forest y SVM usando un kernell lineal. 

13 - Crime analyses using R.

   Se construye un modelo de regresión multivariante para predecir el número de crímenes usando datos históricos del crimen en la ciudad de Chicago. Se utiliza maptools para poder realizar geocode y representación de datos sobre un mapa. El modelo de regresión utilizado es el basado una distribución binomial negativa, utilizando para su entrenamiento el paquete MASS (funcion glm.nb() ).

14 - Football Mining with R.

   Se realiza un modelo de clasificación utilizando un dataset con diferentes datos estadísticos sobre los partidos de futbol que tuvieron lugar en la temporada 2010-2011 de la Serie A italiana. Con datos como el número de tiros a puerta, faltas, balones recuperados, asistencias de gol, porcentaje de posesión... se pretende crear un sistema predictivo para predecir si el partido acabará en victoria, empate o derrota del equipo local.
   Se utiliza Random Forest para extraer las 13 mejores variables explicatorias del conjunto de 481 características inicial (variable selection). Posteriormente se utiliza PCA para la reducción de dimensionalidad; se realiza PCA de forma separada para las variables relacionadas con el equipo local y con el visitante (6 y 7 variables de las 13 respectivamente), para obtener finalmente 6 variables con las que implementar el clasificador. Se implementan diferentes clasificadores: Random Forest, red neuronal (perceptrón multicapa), k vecinos próximos, clasificador Naive Bayes y un modelo de regresión logística multinomial. Se incluye una tabla donde se comenta el proceso seguido y los paquetes utilizados en cada paso:
 Aparte de los modelos de clasificación utilizados, se habla sobre otras posibilidades:
  • Basados en árboles: gradient boosting machine (paquete gbm), árboles condicionales (paquete party) y logic forest (paquete LogicForest).
  • Basados en redes Bayesianas: Bayesian belief network (paquete bnlearn).
  • SVM (paquetes e1071, kernlab, klar, svmpath).
   También se habla de mejoras utilizando técnicas de balanceado entre clases: sobremuestreo, submuestreo, boosting, bagging y submuestreo aleatorio repetido. Se habla de los paquetes caret para realizar submuestreo/sobremuestreo y del paquete DMwR y la función SMOTE para generar muestras artificiales de la clase minoritaria, submuestreando simultaneamente el resto de clases.   

15 - Analyzing Internet DNS (SEC) Traffic with R for Resolving Platform Optimization.

   Se utiliza R para estudiar el tráfico DNS y mejorar la carga de un servidor reduciendo el número de resoluciones. Se implementa un sistema de balanceado de carga basado en la partición del tráfico DNS entre varios servidores con respecto al FQDN solicitado.
   Se analiza el trafico DNS para extraer ciertas variables que caractericen las FQDN y permitan definir una tabla de enrutado, procesando las peticiones con un servidor diferente dependiendo de estas características. Existen 27 características relacionadas con las FQDN en una petición DNS. Se utiliza PCA ( función prcomp() paquete stats ) para reducir dimensionalidad, obteniendose 10 variables compuestas. Del estudio del proceso PCA se deriva un método de selección de variables, escogiendo 7 variables. Utilizando estas variables se realiza un clustering, con el objetivo de separar las FQDN en diferentes grupos dependiendo de sus costes.