Cómo trabajar con las API InnovaChallenge MX y CartoDB APIs

Cómo trabajar con las API InnovaChallenge MX y CartoDB APIs
Cómo trabajar con las API InnovaChallenge MX y CartoDB APIs

BBVA API Market

En esta publicación, aprenderemos a obtener información de una API REST, que proporcionada datos JSON, y la almacena en una CartoDB para poder utilizarla después para crear visualizaciones de datos rápida y fácilmente. En particular, recopilaremos información de la API de datos de BBVA, que se ha colocado en línea para el encuentro de programadores InnovaChallengeMX

Utilizaremos Python, un lenguaje muy fácil de utilizar, que cuenta con muchas características interesantes para la manipulación de datos, como el módulo incorporado json o la biblioteca de solicitudes, para gestionar las solicitudes de HTTP.

Probablemente deberemos tomar algunas decisiones de codificación que no son las mejores si queremos crear un código comprobable y sólido para publicarlo oficialmente, pero solo lo usaremos para realizar pruebas rápidas.

Por tanto, necesitaremos:

    · Una cuenta CartoDB gratuita. Se puede conseguir aquí. Necesitaremos la clave de la API para realizar llamadas SQL. Para obtenerla, basta con ir a https://YOURUSER.cartodb.com/your_apps, después de registrarse

    · Una cuenta de desarrollador de BBVA gratuita. Posteriormente, comprobar este enlace para averiguar cómo generar una cadena de autenticación que utilizaremos para realizar las llamadas

    · Un archivo de texto con varias líneas, seguidas de la clave=formato de valor, que contenga los parámetros para la llamada de la API de BBVA. Es solo una de las formas para pasar la información al script. El archivo debe quedar así

    · El intérprete de Python. Se puede descargar aquí

    · La biblioteca de solicitudes de Python, para realizar solicitudes de HTTP. Las instrucciones para instalar esta biblioteca se encuentran aquí. Y si eres usuario de Debian/Ubuntu es tan sencillo como:

sudo apt-get install python-requests

Eso es todo. Ahora, empecemos

Para nuestra prueba, usaremos la API de datos de BBVA, que BBVA proporciona para InnovaChallengeMX. El proceso cuenta con 4 pasos generales:

    1. Elegir un modelo de datos que funcione para nosotros y traducirlo a CartoDB, en forma de tabla o tablas de PostgreSQL.

    2. Realizar solicitudes a la API fuente y obtener la respuesta JSON

    3. Para cada solicitud, transformar la respuesta del objeto JSON en una frase SQL para introducir datos en nuestro modelo de datos

    4. Plantear una consulta usando la API de SQL CartoDB y la consulta INSERT integrada en el paso anterior.

Al leer la API de datos de BBVA, encontramos una solicitud interesante. Proporciona estadísticas de pagos con tarjeta de crédito para un mosaico (una zona de 550 x 500 m) y categoría comercial concreta, diferenciados por segmentos de sexo y edad. Bastante completos. Trabajaremos con ello, pero aplanando la respuesta JSON un poco para que quepa en este esquema:

stats_table(the_geom, the_date, age, gender, num_cards, num_payments, avg)

El significado de los campos es el siguiente:

    · the_geom: punto que representa el centro de un mosaico de 550 x 500 m

    · the_date: fecha a comprobar

    · age: rango de edad para los pagadores

    · gender: sexo de los pagadores

    · num_cards: número de distintas tarjetas de crédito que se usaron en esa fecha en lugares dentro del mosaico

    · num_payments: número de pagos realizados en esa fecha en lugares dentro del mosaico

    · avg: valor promedio de los pagos realizados en esa fecha en lugares dentro del mosaico

Para rellenar esta tabla, necesitaremos una lista de puntos (X,Y) para llamar a la API de BBVA, a fin de poder mostrar algunos datos. Podemos conseguir una lista de los puntos más populares de la API de BBVA usando esta consulta.

Ahora podemos crear una tabla vacía en CartoDB, renombrarla como stats_table, crear las columnas que necesitemos y rellenarla con datos. ¿Cómo?

En primer lugar, haremos clic en el icono New table de la parte derecha

Seleccionaremos la opción Empty table

Se creará una tabla llamada untitled_table y nos conducirá a la vista de tabla. Haciendo doble clic sobre el nombre de la tabla lo cambiamos. La renombraremos stats_table

Vamos a ver nuestra nueva tabla. Ya contiene algunas columnas:

    · cartodb_id: una serie. Se rellenan automáticamente con cada inserción

    · the_geom: nuestra geometría (será un punto en nuestro ejemplo)

    · description: no lo usaremos

    · name: no lo usaremos

    · created_at: marca de tiempo. Toma automáticamente el momento actual como valor

    · updated_at: marca de tiempo. Toma automáticamente el momento actual como valor cuando se modifica la fila

Necesitamos más campos: the_date, age, gender, num_cards, num_payments, avg. Por tanto, los añadimos usando el botón Añadir columna en la parte inferior derecha.

Respecto al tipo de datos, usaremos date para the_date, string para age y gendery number para num_cards, num_payments y avg.

Ahora que hemos creado nuestra solicitud de API y nuestras tablas podemos escribir nuestro traductor, de la API de JSON de BBVA a CartoDB. El script de Python debe quedar así.

En primer lugar, las importaciones

#!/usr/bin/python

# -*- coding: utf-8 -*-

import sys, requests

from os import environ

Como hemos comentado, importamos la biblioteca de solicitudes. Incluye la posibilidad de manejar datos json, por tanto, no es necesario incluir el módulo json.

Ahora, definimos todas las llamadas de url que usaremos:

bbva_url_most_popular_tiles = "https://apis.bbvabancomer.com/datathon/info/tiles"

bbva_url_stats = "https://apis.bbvabancomer.com/datathon/tiles/%s/%s/cards_cube"

cartodb_url_sql = "http://%s.cartodb.com/api/v2/sql"

Los elementos %s serán sustituidos por valores clave, como nombres de usuario o ubicaciones específicas.

Ahora, algunas funciones útiles

# Just read an environment variable, and raise an error if it isn’t found

def get_env_variable(var_name):

   try:

       return environ[var_name]

   except KeyError:

       msg = "Set the %s environment variable"

       error_msg = msg % var_name

       raise Exception(error_msg)

# Read our secret params from environment variables. You could also provide them

# as input parameters...

def read_secret_params():

   cdb_user = get_env_variable('cdb_user')

   cdb_apikey = get_env_variable('cdb_apikey')

   bbva_auth_str = get_env_variable('bbva_auth_str')

   return (cdb_user, cdb_apikey, bbva_auth_str)

# Read the query parameters for BBVA API request

def read_payload_from_file(file_path):

   myvars = {}

   with open(file_path) as myfile:

       for line in myfile:

           name, var = line.partition("=")[::2]

           if var:

               myvars[name.strip()] = var.replace("\n", "")

   return myvars

Empecemos con la diversión leyendo parámetros secretos de entrada como el usuario de CartoDB y la clave de API y la cadena de autenticación de BBVA. Preferimos leer estos valores de variables de entorno. De este modo, no es necesario escribirlos (ojos curiosos pueden estar observándonos). Puede que no sea la mejor manera de gestionar claves privadas, pero funciona para nuestros fines.

#TODO: Parse input args

#Read secret params

(cdb_user, cdb_api_key, bbva_auth_str) = read_secret_params()

#We will need this header

headers = {'Authorization' : 'Basic %s' % bbva_auth_str}

#We have all the arguments for the query stored in a text file

bbva_payload = read_payload_from_file(argv[1])

Es hora de obtener los puntos para crear llamadas de API de BBVA. Para ello, plantearemos una consulta de SQL sencilla para obtener todos los puntos de la API de BBVA

#Now, get the ranking of the most active zip codes (with the greatest number of payments) in descending order

r = requests.get(bbva_url_most_popular_tiles, headers=headers)

data = r.json()

El método json() transforma automáticamente la respuesta JSON en un diccionario Python. Mucho más fácil de manejar. Ahora, poblamos nuestro propio diccionario usando nombres de columnas como claves del diccionario y valores extraídos de datos como valores del diccionario. Posteriormente, usamos el diccionario para crear la consulta de SQL INSERT. Paso a paso.

En primer lugar, obtenemos el punto de la respuesta JSON de CartoDB y lo usamos para realizar una llamada a la API de BBVA

if 'data' in data and 'coordinates' in data['data']:

       for point in data['data']['coordinates']:

           longitude = point[0]

           latitude = point[1]

           r2 = requests.get(bbva_url_stats % (latitude, longitude), params=bbva_payload, headers=headers)           

    #Get the response in a dict

           data2 = r2.json()

En segundo lugar, analizamos los metadatos de esta respuesta. Es básicamente un índice que contiene todos los grupos de rangos de edad y sexos. 

                   if 'metadata' in data2 and 'hash_description' in data2['metadata'] and 'ranges' in data2['metadata']['hash_description'] and 'data' in data2 and 'stats' in data2['data']:

            # Parse metadata

            genders = {}

            ages = {}

            for range in data2['metadata']['hash_description']['ranges']:

                if 'name' in range and 'values' in range:

                    if range['name'] == 'gender':

                        for gender in range['values']:

                            if 'label' in gender and 'description' in gender:

                                genders[str(gender['label'])] = str(gender['description'])

                            elif range['name'] == 'age':

                                for age in range['values']:

                                    if 'label' in age and 'description' in age:

                                        ages[str(age['label'])] = str(age['description'])        

Una vez analizados los metadatos, analizamos los datos. Usaremos el índice creado en el paso anterior para obtener el rango de edad y sexo de él.

                #Now, parses data

          for stat in data2['data']['stats']:

              insert_dict = {}

              if 'date' in stat:

                  insert_dict['the_date'] = "'" + str(stat['date']) + "'"

                  if 'cube' in stat:

                      cubes = stat['cube']

                      # Here, we've flatenning the structure, to fin into our data model

                      for cube in cubes:

                          if 'hash' in cube:

                              l = str(cube['hash']).split('#')

                              insert_dict['age'] = "'" + ages[l[1]] + "'"

                              insert_dict['gender'] = "'" + genders[l[0]] + "'"

                           if 'num_cards' in cube:

                              insert_dict['num_cards'] = str(cube['num_cards'])

                           if 'num_payments' in cube:

                              insert_dict['num_payments'] = str(cube['num_payments'])

                           if 'avg' in cube:

                              insert_dict['avg'] = str(cube['avg'])

                           insert_dict['the_geom'] = "ST_SetSRID(ST_MakePoint(%d, %d), 4326)" % (longitude,latitude)

                           sql2 = "insert into stats_by_gender_and_age(%s) values(%s)" % (','.join(insert_dict.keys()),','.join(insert_dict.values()))

                           print sql2

                           #Insert entry in CartoDB

                           payload2 = {'q': sql2, 'api_key': cdb_api_key}

                           r3 = requests.get(cartodb_url_sql % cdb_user, params=payload2)

Muy bien. Ya está. Solo tenemos que añadir la llamada al método main().

if __name__ == '__main__':

   try:

       main(sys.argv)

   except Exception, e:

       print e

       sys.exit(1)

Y eso es todo. Podemos llamar al script de este modo (asumiendo que lo hemos denominado bbva2cartodb.py)

python bbva2cartodb.py params.txt

No debemos olvidar que params.txt es el archivo con los parámetros respecto a la consulta de la API de BBVA.

Aquí se encuentra el código fuente de este script (por supuesto, se puede clonar el repo si se prefiere)

Al final, tendremos una tabla CartoDB que contenga estadísticas útiles. Ya podemos realizar visualizaciones con ella. Esto lo veremos en otra publicación, pero, por supuesto, ya podemos jugar con ella usando el asistente de map view. Una pista, la visualización torque parece prometedora…

Prepárate para más publicaciones

Descubre más sobre las APIs de BBVA aquí.

También podría interesarte