Dibujando 100k tweets de mi ciudad

[Esta entrada apareció originalmente en inglés en mi blog].

Hace tiempo que he querido jugar con la API de Twitter. El pasado verano se me ocurrió que podría ser interesante dibujar un mapa de mi ciudad (Murcia, España, bella ciudad con comida increible) mostrando un heatmap de tweets.

La idea es que dibujando esos tweets podría encontrar patrones interesantes de mi ciudad. Por ejemplo:

  • ¿Desde qué áreas la gente tuitea más?
  • ¿Qué horas del día son las más activas?
  • ¿Cuales son los lugares más felices/tristes?
  • ¿Hay alguna comunidad tuitera local extranjera?

Con esas ideas en la cabeza empecé la investigación. Primero, necesitaba una librería para interactuar con la API de Twitter. Después de probar la extensa cantidad de wrappers disponibles me decidí por Tweepy. Posee una interfaz simple y agradable de usar y está bien mantenida.

(INCISO, todo el código y los datos que se usan en esta entrada está disponible en Github).

De cara a obtener los tweets de mi ciudad en tiempo real decidí ajustarme al API Streaming de Twitter. Este es el código sencillo que usé:

 
import json
from tweepy import Stream
from tweepy import OAuthHandler
from tweepy.streaming import StreamListener

ckey = CONSUMER_KEY
csecret = CONSUMER_SECRET
atoken = APP_TOKEN
asecret = APP_SECRET

murcia = [-1.157420, 37.951741, -1.081202, 38.029126] #Venid a verla, es una ciudad muy bonita!

file =  open('tweets.txt', 'a')

class listener(StreamListener):

    def on_data(self, data):
        # La API de Twitter devuelve datos en formato JSON, asi que hay que decodificarlos.
        try:
            decoded = json.loads(data)
        except Exception as e:
            print e #no queremos que el script se pare
        return True

        if decoded.get('geo') is not None:
            location = decoded.get('geo').get('coordinates')
        else:
            location = '[,]'
        text = decoded['text'].replace('\n',' ')
        user = '@' + decoded.get('user').get('screen_name')
        created = decoded.get('created_at')
        tweet = '%s|%s|%s|s\n' % (user,location,created,text)

        file.write(tweet)
        print tweet
        return True

    def on_error(self, status):
        print status

if __name__ == '__main__':
print 'Empezando...'

auth = OAuthHandler(ckey, csecret)
auth.set_access_token(atoken, asecret)
twitterStream = Stream(auth, listener())
twitterStream.filter(locations=murcia)
 

El script solo requiere las claves y secretos de la API de Twitter además de un par de puntos (latitudes y longitudes de los puntos). La API de Twitter solo devolverá tweets cuyas lat/lon estén dentro de los límites definidos (al menos, en teoria).

INCISO: Si no quieres tener que descargarte los tweets puedes bajarte el archivo en Github

Dejé este script ejecutándose durante meses en una de mis instancias en Digital Ocean. Obtuve alrededor de 600K tweets. De esos 600K, alrededor de 1/6 estaban geolocalizados. Por tanto, me quedé con 100K tweets para hacer el gráfico.

Una vez que tenemos los datos de Twitter parseados, solo tuve que buscar una buena librería para dibujar heatmaps. La mejor que encontré, tanto por su simplicidad (solo un fichero)como por su nivel de ajustes, fue Heatmap.py.

Puedes echar un vistazo en Github para ver como usé heatmap. Aquí puedes varios de los mapas que dibujé:


Bonito, ¿verdad?

En la próxima entrada os mostraré como aplicar análisis de sentimientos al conjunto de datos para encontrar los lugares de la ciudad más alegres/tristes.

Manuel Garrido

Manuel ha estado 4 años en Nueva York, primero trabajando como Senior Analyst para la NBC y luego como Data Scientist. Tras trabajar en varias empresas, ahora trabaja como Data Scientist Consultant, tanto para clientes españoles como extranjeros. Si necesitas ayuda, no dudes en contactarle!

More Posts - Website

Follow Me:
Twitter

5 thoughts on “Dibujando 100k tweets de mi ciudad

  1. Se ve interesante, el tema voy a probarlo apenas pueda, pero una consulta esas latitudes y longitudes las busco en el mapa y me aparecen en una cuidad en kenia xD, las probé en google maps, por eso mi consulta, como obtengo las coordenadas de mi zona donde quiero probar?

    Saludos

  2. Hola Macjob,

    Has comprobado que efectivamente, estas buscando latitudes y longitudes y no longitudes y latitudes? Hay sistemas que usan lat,lon y otros usan lon, lat (no es standard desafortunadamente).

  3. ¡Hola, Manuel!

    Antes que nada, ¡gracias por tus aportaciones al campo del NLP!

    Verás, acabo de empezar un MSc y ando en búsqueda de un proyecto de Research a desarrollar. Una de las cosas que me apasiona leer es sobre NLP y Opinion Mining; sin embargo, llevo dedicándome al área de tecnología como Oracle DBA, desde ya casi 14 años. Esto me especializó en muchas cosas, pero me alejó de otras; por ejemplo, la programación OOP.

    Yendo al grano: si pudieras darme un consejo, ¿por dónde me recomedarías empezar para realizar un Análisis de Sentimientos “a bajo nivel” (por ejemplo, descargar un data set de tweets y buscar en éste alguna tendencia “básica” en “Política o Gobierno de un país”)?, pero tomando en cuenta que tengo que entregar el proyecto de Research en 3 meses. ¿Lo ves factible? Mis habilidades son: RDBMS, Linux, Replicación de Datos, BBDD > 25 TB, PLSQL, Shell / Bash Scripting.

    En caso de que lo veas factible, ¿por dónde me recomendarías empezar? Me podrías dar, a gran escala por supuesto, una serie de pasos a seguir; digamos: “instala Python, descarga y lee la doc. de tweepy, activa el feed de Twitter y descarga tweets durante…” etc etc. ¡Lo que se te ocurra es bienvenido y extremadamente agradecido!

    Pregunta final y con menos importancia, que esto ya lo puedo seguir investigando: debido a la política de Twitter, ¿no es posible descargar tweets antiguos? Es decir, si quiero buscar una tendencia cronológica, puedo comparar tweets actuales versus el año pasado?

    De nuevo, mil gracias por leerme y perdona tanta pregunta y texto!

    Un saludo desde Cambridge, UK!
    Carlos.

Leave a Reply

Your email address will not be published. Required fields are marked *