Medición del sentimiento a nivel mundial

Se toma la valoración de las palabras, según las listas contenidas en AFINN-111.txt (para ingles), nspa.txt (palabras negativas en espanol) y ppsa.txt (palabras positivas en ingles). Luego se ejecuta la valoracion del sentimiento de cada tweet, usando la lista de tweets descargados previamente.

Obtendremos un diccionario con el código de cada país (según el origen del tweet) y la valoracion total del sentimiento para ese país.

In [4]:
#medicion del sentimiento en twitter
import json

#abrimos el diccionario de palabras
contador=0
dicEstados={}

archDic=open("./AFINN-111.txt","r")
dicSentimiento={}
for linea in archDic:
    texto=linea.split("\t")
    palabra=texto[0]
    valor=int(texto[1])
    dicSentimiento[palabra]=valor
    contador=contador+1


archDic=open("./nspa.txt","r")
dicSentimiento={}
for linea in archDic:
    texto=linea
    palabra=texto[0]
    valor=-1
    dicSentimiento[palabra]=valor
    contador=contador+1

archDic=open("./pspa.txt","r")
for linea in archDic:
    texto=linea
    palabra=texto[0]
    valor=1
    dicSentimiento[palabra]=valor
    contador=contador+1

print "Diccionario cargado! "+str(contador)+" palabras"

def sentimiento(texto):
    sentimiento=0
    arrTexto=texto.split(" ")
    for palabra in arrTexto:
        if (dicSentimiento.has_key(palabra)):
            sentimiento=sentimiento+dicSentimiento[palabra]
    return sentimiento
    
#procesamos los tweets
arch=open("./salida.out", "r")
i=0
for linea in arch:
    datos=json.loads(linea)
    #procesamos el tweet
    if (datos.has_key("place")):
        #verificamos si esta en EEUU
        ubicacion=datos["place"]
        if (ubicacion!=None):
            
            if (ubicacion["country_code"]!=None):
                #ubicacion_completa=ubicacion["full_name"]
                #arrUbicacion=ubicacion_completa.split(",")
                estado=ubicacion["country_code"]
                #procesamos el tweet
                tweet=datos["text"].encode('utf-8')
                tweet=tweet.decode('utf-8')
                sent=sentimiento(tweet)
                #print "Tweet: "+str(i)+"\tUbicacion: "+str(estado)+"\t"+str(sent)+"\t"+tweet
                #pp.pprint(datos)
                #agregamos al diccionario de estados
                #estado=arrUbicacion[1]
                if (dicEstados.has_key(estado)):
                    dicEstados[estado]=dicEstados[estado]+sent
                else:
                    if (sent!=0):
                        dicEstados[estado]=sent
                i=i+1
print "Resultados:"
print(dicEstados)
Diccionario cargado! 9265 palabras
Resultados:
{u'BE': 0, u'FR': 7, u'DK': 1, u'DO': -1, u'TR': 8, u'CH': 1, u'BO': 3, u'ZA': 1, u'BW': 1, u'BR': 202, u'AE': 3, u'PR': 1, u'RU': 3, u'NL': 2, u'PT': 0, u'RS': 4, u'PY': 5, u'MY': 7, u'NG': 1, u'CU': 2, u'TH': 3, u'PE': 0, u'NP': 1, u'PK': 3, u'PH': 6, u'PL': -1, u'EC': 1, u'DE': 3, u'CO': 8, u'VE': 12, u'CL': 13, u'CA': 6, u'IT': 7, u'VN': 1, u'SA': 0, u'AR': 75, u'AU': 1, u'GB': 24, u'IN': 3, u'MA': 3, u'IE': 2, u'ID': 3, u'ES': 40, u'UY': 14, u'KE': 2, u'SG': 2, u'SV': 1, u'US': 100, u'UG': 1, u'UA': 1, u'MX': 10, u'SE': 3}

Obtenemos el equivalente de codigos de paises, para esto, previamente se ha generado un archivo de texto con las equivalencias entre los códigos de 2 y 3 caracteres.

In [2]:
archPais=open("./paises.txt","r")
dicPais={}
for linea in archPais:
    texto=linea.split("\t")
    pais2=texto[1]
    pais3=texto[2]
    dicPais[pais2]=pais3
print dicPais
{'BD': 'BGD', 'BE': 'BEL', 'BF': 'BFA', 'BG': 'BGR', 'BA': 'BIH', 'BB': 'BRB', 'WF': 'WLF', 'BL': 'BLM', 'BM': 'BMU', 'BN': 'BRN', 'BO': 'BOL', 'BH': 'BHR', 'BI': 'BDI', 'BJ': 'BEN', 'BT': 'BTN', 'JM': 'JAM', 'BV': 'BVT', 'BW': 'BWA', 'WS': 'WSM', 'BR': 'BRA', 'BS': 'BHS', 'JE': 'JEY', 'BY': 'BLR', 'BZ': 'BLZ', 'RU': 'RUS', 'RW': 'RWA', 'RS': 'SRB', 'TL': 'TLS', 'RE': 'REU', 'TM': 'TKM', 'TJ': 'TJK', 'RO': 'ROU', 'TK': 'TKL', 'GW': 'GNB', 'GU': 'GUM', 'GT': 'GTM', 'GS': 'SGS', 'GR': 'GRC', 'GQ': 'GNQ', 'GP': 'GLP', 'JP': 'JPN', 'GY': 'GUY', 'GG': 'GGY', 'GF': 'GUF', 'GE': 'GEO', 'GD': 'GRD', 'GB': 'GBR', 'GA': 'GAB', 'GN': 'GIN', 'GM': 'GMB', 'GL': 'GRL', 'GI': 'GIB', 'GH': 'GHA', 'OM': 'OMN', 'TN': 'TUN', 'JO': 'JOR', 'HR': 'HRV', 'HT': 'HTI', 'HU': 'HUN', 'HK': 'HKG', 'HN': 'HND', 'HM': 'HMD', 'VE': 'VEN', 'PR': 'PRI', 'PS': 'PSE', 'PW': 'PLW', 'PT': 'PRT', 'KN': 'KNA', 'PY': 'PRY', 'IQ': 'IRQ', 'PA': 'PAN', 'PF': 'PYF', 'PG': 'PNG', 'PE': 'PER', 'PK': 'PAK', 'PH': 'PHL', 'PN': 'PCN', 'PL': 'POL', 'PM': 'SPM', 'ZM': 'ZMB', 'EH': 'ESH', 'EE': 'EST', 'EG': 'EGY', 'ZA': 'ZAF', 'EC': 'ECU', 'IT': 'ITA', 'VN': 'VNM', 'SB': 'SLB', 'ET': 'ETH', 'SO': 'SOM', 'ZW': 'ZWE', 'SA': 'SAU', 'ES': 'ESP', 'ER': 'ERI', 'ME': 'MNE', 'MD': 'MDA', 'MG': 'MDG', 'MF': 'MAF', 'MA': 'MAR', 'MC': 'MCO', 'UZ': 'UZB', 'MM': 'MMR', 'ML': 'MLI', 'MO': 'MAC', 'MN': 'MNG', 'MH': 'MHL', 'MK': 'MKD', 'MU': 'MUS', 'MT': 'MLT', 'MW': 'MWI', 'MV': 'MDV', 'MQ': 'MTQ', 'MP': 'MNP', 'MS': 'MSR', 'MR': 'MRT', 'IM': 'IMN', 'UG': 'UGA', 'TZ': 'TZA', 'MY': 'MYS', 'MX': 'MEX', 'IL': 'ISR', 'FR': 'FRA', 'AW': 'ABW', 'SH': 'SHN', 'SJ': 'SJM', 'FI': 'FIN', 'FJ': 'FJI', 'FK': 'FLK', 'FM': 'FSM', 'FO': 'FRO', 'NI': 'NIC', 'NL': 'NLD', 'NO': 'NOR', 'NA': 'NAM', 'VU': 'VUT', 'NC': 'NCL', 'NE': 'NER', 'NF': 'NFK', 'NG': 'NGA', 'NZ': 'NZL', 'NP': 'NPL', 'NR': 'NRU', 'NU': 'NIU', 'CK': 'COK', 'CI': 'CIV', 'CH': 'CHE', 'CO': 'COL', 'CN': 'CHN', 'CM': 'CMR', 'CL': 'CHL', 'CC': 'CCK', 'CA': 'CAN', 'CG': 'COG', 'CF': 'CAF', 'CD': 'COD', 'CZ': 'CZE', 'CY': 'CYP', 'CX': 'CXR', 'CR': 'CRI', 'CV': 'CPV', 'CU': 'CUB', 'SZ': 'SWZ', 'SY': 'SYR', 'KG': 'KGZ', 'KE': 'KEN', 'SS': 'SSD', 'SR': 'SUR', 'KI': 'KIR', 'KH': 'KHM', 'SV': 'SLV', 'KM': 'COM', 'ST': 'STP', 'SK': 'SVK', 'KR': 'KOR', 'SI': 'SVN', 'KP': 'PRK', 'KW': 'KWT', 'SN': 'SEN', 'SM': 'SMR', 'SL': 'SLE', 'SC': 'SYC', 'KZ': 'KAZ', 'KY': 'CYM', 'SG': 'SGP', 'SE': 'SWE', 'SD': 'SDN', 'DO': 'DOM', 'DM': 'DMA', 'DJ': 'DJI', 'DK': 'DNK', 'DE': 'DEU', 'YE': 'YEM', 'DZ': 'DZA', 'US': 'USA', 'UY': 'URY', 'YT': 'MYT', 'UM': 'UMI', 'LB': 'LBN', 'LC': 'LCA', 'LA': 'LAO', 'TV': 'TUV', 'TW': 'TWN', 'TT': 'TTO', 'TR': 'TUR', 'LK': 'LKA', 'LI': 'LIE', 'LV': 'LVA', 'TO': 'TON', 'LT': 'LTU', 'LU': 'LUX', 'LR': 'LBR', 'LS': 'LSO', 'TH': 'THA', 'TF': 'ATF', 'TG': 'TGO', 'TD': 'TCD', 'TC': 'TCA', 'LY': 'LBY', 'VA': 'VAT', 'VC': 'VCT', 'AE': 'ARE', 'AD': 'AND', 'AG': 'ATG', 'VG': 'VGB', 'AI': 'AIA', 'VI': 'VIR', 'IS': 'ISL', 'IR': 'IRN', 'AM': 'ARM', 'AL': 'ALB', 'AO': 'AGO', 'AN': 'ANT', 'AQ': 'ATA', 'AS': 'ASM', 'AR': 'ARG', 'AU': 'AUS', 'AT': 'AUT', 'IO': 'IOT', 'IN': 'IND', 'AX': 'ALA', 'AZ': 'AZE', 'IE': 'IRL', 'ID': 'IDN', 'UA': 'UKR', 'QA': 'QAT', 'MZ': 'MOZ'}

Obtenemos un diccionario con el código de país de 3 caracteres, y su valor de sentimiento

In [5]:
datosPais={}
for pais in dicEstados:
    codPais=dicPais[pais]
    datosPais[codPais]=(dicEstados[pais])
print datosPais
{'GBR': 24, 'NGA': 1, 'BEL': 0, 'DOM': -1, 'SWE': 3, 'DEU': 3, 'PER': 0, 'IDN': 3, 'MEX': 10, 'BOL': 3, 'CAN': 6, 'PAK': 3, 'COL': 8, 'USA': 100, 'PRT': 0, 'SGP': 2, 'MYS': 7, 'PRI': 1, 'ECU': 1, 'BWA': 1, 'POL': -1, 'NLD': 2, 'PRY': 5, 'SAU': 0, 'SRB': 4, 'FRA': 7, 'CHE': 1, 'ESP': 40, 'SLV': 1, 'CHL': 13, 'DNK': 1, 'UKR': 1, 'AUS': 1, 'IRL': 2, 'CUB': 2, 'VEN': 12, 'URY': 14, 'THA': 3, 'NPL': 1, 'MAR': 3, 'PHL': 6, 'ZAF': 1, 'TUR': 8, 'ITA': 7, 'UGA': 1, 'ARE': 3, 'ARG': 75, 'IND': 3, 'RUS': 3, 'VNM': 1, 'BRA': 202, 'KEN': 2}

Dibujamos el mapa mundial, usando los datos finales obtenidos

In [9]:
import vincent
from vincent.values import ValueRef

vincent.initialize_notebook()

#generamos los datos para los paises
import pandas as pd
country_codes = datosPais.keys()
country_values= datosPais.values()
country_df=pd.DataFrame({'pais': country_codes, 'valor':country_values}, dtype=int)


world_topo='world-countries.topo.json'
geo_data=[{'name':'world-countries', 'url':world_topo, 'feature':'world-countries'}]

vis=vincent.Map(projection = 'mercator', data=country_df, geo_data=geo_data, scale=300, data_key='pais', data_bind='valor', map_key={'world-countries': 'id'})
#vis.marks[0].properties.enter.stroke_opacity=ValueRef(value=0.5)
#vis.scales['color'].domain=[0, 250]
#vis.legend(title='Sentimiento')
vis.scales['color'].type='threshold'
vis.scales['color'].domain=[0,20,40,60,80,100,120,140,160,180,200,220,240]
vis.display()

Visualizamos el dataframe utilizado

In [10]:
print country_df
   pais  valor
0   GBR     24
1   NGA      1
2   BEL      0
3   DOM     -1
4   SWE      3
5   DEU      3
6   PER      0
7   IDN      3
8   MEX     10
9   BOL      3
10  CAN      6
11  PAK      3
12  COL      8
13  USA    100
14  PRT      0
15  SGP      2
16  MYS      7
17  PRI      1
18  ECU      1
19  BWA      1
20  POL     -1
21  NLD      2
22  PRY      5
23  SAU      0
24  SRB      4
25  FRA      7
26  CHE      1
27  ESP     40
28  SLV      1
29  CHL     13
30  DNK      1
31  UKR      1
32  AUS      1
33  IRL      2
34  CUB      2
35  VEN     12
36  URY     14
37  THA      3
38  NPL      1
39  MAR      3
40  PHL      6
41  ZAF      1
42  TUR      8
43  ITA      7
44  UGA      1
45  ARE      3
46  ARG     75
47  IND      3
48  RUS      3
49  VNM      1
50  BRA    202
51  KEN      2
In [ ]: