Compartimos el webinar realizado en el grupo de Meetup De 0 a 100 en cloud computing donde tratamos una introducción básica a los servicios cloud, un demo básico sobre Microsoft Azure aprovisionando servicios usando el marketplace, cursos y laboratorios de autoformación.
El análisis de sentimiento utiliza técnicas de procesamiento de lenguaje natural (NLP) para obtener conclusiones sobre textos producidos por personas y analizar en ellos rasgos de interés asociados a emociones positivas o negativas. Se requiere un modelo que ya haya sido entrenado con textos que nos permita obtener valores cuantificables.
Hoy nos apoyaremos en la guía de Free Code Camp “Basic data analysis on Twitter with Python” para hacer Análisis de Sentimientos sobre Twitter usando la librería TextBlob de Python que dispone de modelos de NLP para diversos usos.
Primero debemos tener instalada la librería tweepy.
#pip3 install tweepy
Si estás usando Python 3.7 tendrás un error al tratar de usar la librería que todavía no ha sido corregido en la última versión disponible (hoy, eso puede variar en poco tiempo) para resolverlo usamos la siguiente recomendación de StackOverFlow para reemplazar una palabra reservada Async en el archivo streaming.py de la librería.
La ubicación del archivo varía según tu sistema operativo, en Mac estará ubicado en /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tweepy/streaming.py edítala con un editor de texto plano y reemplaza todas las ocurrencias de async por async_ grabas y listo. Versiones anteriores a 3.7 de Python no requieren este cambio.
Previamente debemos tener la librería NLTK instalada, las instrucciones para hacerlo puedes verlas AQUÍ, para actualizarla si ya la tienes instalada
Si quieres saber más sobre la librería puede visitar su sitio en GitHub, tiene más herramientas de análisis para texto en Inglés, si deseamos análisis en español es necesario utilizar otra diferente https://github.com/sloria/textblob Dentro del script analizaremos los tweets cuya propiedad “lang” = “en” es decir aquellos cuyo lenguaje fue identificado como inglés. Para otras propiedades del tweet pueden consultar la documentación de Twitter.
Tendremos las claves de aplicación de Twitter en un archivo separado, de modo que no queden en el mismo código que estamos empleando y puedan reusarse en otros scripts, llamaremos a este script de claves twkeys.py
Recientemente Twitter cambió su forma de usar credenciales y ahora debe aplicarse por una cuenta de desarrollador, el proceso para aplicar puedes verlo en https://apps.twitter.com
Este es el código que usamos para realizar el análisis, el resultado nos mostrará las gráficas de dispersión de dos cuentas, el promedio simple y promedio ponderado de sentimiento de ambas.
#Importar consumer API de Twitter https://github.com/tweepy/tweepy
import tweepy
#importar las credenciales de Twitter de un script
import twkeys
#Importar librería para Sentiment Analysis
from textblob import TextBlob
from time import sleep
from datetime import datetime
#Importar para graficar los Datos
#Para Jupyter notebooks quitar el comentario a la siguiente línea
#%matplotlib inline
import matplotlib.pyplot as plt
#Importar para calcular promedio ponderado
import numpy as np
#Credenciales del Twitter API que están el el script twkeys.py
consumer_key = twkeys.consumer_key()
consumer_secret = twkeys.consumer_secret()
access_key = twkeys.access_key()
access_secret = twkeys.access_secret()
def get_all_tweets(screen_name,graph_id):
#Este método solo tiene permitido descargar máximo los ultimos 3240 tweets del usuario
#Especificar aquí durante las pruebas un número entre 200 y 3240
limit_number = 3240
#autorizar twitter, inicializar tweepy
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_key, access_secret)
api = tweepy.API(auth)
#inicializar una list to para almacenar los Tweets descargados por tweepy
alltweets = []
#Hacer una petición inicial por los 200 tweets más recientes (200 es el número máximo permitido)
new_tweets = api.user_timeline(screen_name = screen_name,count=200)
#guardar los tweets más recientes
alltweets.extend(new_tweets)
#guardar el ID del tweet más antiguo menos 1
oldest = alltweets[-1].id - 1
#recorrer todos los tweets en la cola hasta que no queden más
while len(new_tweets) > 0 and len(alltweets) <= limit_number:
print ("getting tweets before" + str(oldest))
#en todas las peticiones siguientes usar el parámetro max_id para evitar duplicados
new_tweets = api.user_timeline(screen_name = screen_name,count=200,max_id=oldest)
#guardar los tweets descargados
alltweets.extend(new_tweets)
#actualizar el ID del tweet más antiguo menos 1
oldest = alltweets[-1].id - 1
#informar en la consola como vamos
print (str(len(alltweets)) + " tweets descargados hasta el momento")
#Realizar el análisis de sentimiento de los tweets descargados
#Crear las listas de polaridad polarity_list y frecuencia de polaridad numbers_list
polarity_list = []
numbers_list = []
number = 1
for tweet in alltweets:
if tweet.lang == "en":
try:
analysis = TextBlob(tweet.text)
analysis = analysis.sentiment
#Guardar la polaridad
polarity = analysis.polarity
polarity_list.append(polarity)
#Contar las veces que esa polaridad ha ocurrido
numbers_list.append(number)
number = number + 1
except tweepy.TweepError as e:
print(e.reason)
except StopIteration:
break
#Crear eje cartesiano
plt.figure(graph_id)
axes = plt.gca()
axes.set_ylim([-1, 3])
plt.scatter(numbers_list, polarity_list)
#Calcular el promedio de polaridad, NOTA: No es promedio ponderado
averagePolarity = (sum(polarity_list))/(len(polarity_list))
averagePolarity = "{0:.0f}%".format(averagePolarity * 100)
time = datetime.now().strftime("At: %H:%M\nOn: %m-%d-%y")
#Calcular el promedio ponderado
weighted_avgPolarity = np.average(polarity_list, weights=numbers_list)
weighted_avgPolarity = "{0:.0f}%".format(weighted_avgPolarity * 100)
#Agregar texto con el promedio de sentimiento
plt.text(10, 1.5, "Average Sentiment: " + str(averagePolarity) + "\n" + " Weighted Average Sentiment: " + str(weighted_avgPolarity) + "\n" + time, fontsize=12, bbox = dict(facecolor='none', edgecolor='black', boxstyle='square, pad = 1'))
#Título
plt.title("Sentiment of " + screen_name + " on Twitter")
plt.xlabel("Number of Tweets")
plt.ylabel("Sentiment")
pass
if __name__ == '__main__':
#especificar el nombre de usuario de la cuenta a la cual se descargarán los tweets
get_all_tweets("Add_account_1",200)
get_all_tweets("Add_account_2",300)
#Mostrar las gráfica
plt.show()
Explicamos como acceder a los tweets públicos de un usuario por medio de Python, para almacenarlos en un archivo .csv que posteriormente pueda ser cargado en un DataFrame.
Se requiere instalar la librería tweepy (El manejador de paquetes pip ya debe estar instalado, para instalar pip puedes consultar como Aquí)
pip3 install tweepy
Obtener tokens de acceso para conectarse a Twitter
Llenar los campos mandatorios de nombre, descripción y sitio web. Este último puede no ser una página activa dado que nuestra conexión será de solo lectura
Aceptar los términos y condiciones y dar click en “Crear twitter app”
Una vez creada la aplicación ir a la pestaña de “Permisos” y cambiarlos por “Solo lectura”, esto es importante pues solo la usaremos para descarga de datos, no para publicar nada en tu cuenta.
Recibirás una alerta de que debes esperar a que los permisos se actualicen, una vez actualizados ve a la pestaña “Tokens de acceso”
Dar click sobre “Crear Tokens de acceso” para generar las credenciales que la aplicación usará. Estos datos son privados, cualquiera que los tenga podrá conectarse a twitter a nombre de tu aplicación.
Usa el código a continuación y guárdalo en un archivo de script Python tweets.py
import tweepy #https://github.com/tweepy/tweepy
import csv
#Credenciales del Twitter API
consumer_key = "Agregar Consumer Key"
consumer_secret = "Agregar Consumer Secret"
access_key = "Agregar Access Key"
access_secret = "Agregar Access Secret"
#Remover los caracteres no imprimibles y los saltos de línea del texto del tweet
def strip_undesired_chars(tweet):
stripped_tweet = tweet.replace('\n', ' ').replace('\r', '')
char_list = [stripped_tweet[j] for j in range(len(stripped_tweet)) if ord(stripped_tweet[j]) in range(65536)]
stripped_tweet=''
for j in char_list:
stripped_tweet=stripped_tweet+j
return stripped_tweet
def get_all_tweets(screen_name):
#Este método solo tiene permitido descargar máximo los ultimos 3240 tweets del usuario
#Especificar aquí durante las pruebas un número entre 200 y 3240
limit_number = 3240
#autorizar twitter, inicializar tweepy
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_key, access_secret)
api = tweepy.API(auth)
#inicializar una list to para almacenar los Tweets descargados por tweepy
alltweets = []
#Hacer una petición inicial por los 200 tweets más recientes (200 es el número máximo permitido)
new_tweets = api.user_timeline(screen_name = screen_name,count=200)
#guardar los tweets más recientes
alltweets.extend(new_tweets)
#guardar el ID del tweet más antiguo menos 1
oldest = alltweets[-1].id - 1
#recorrer todos los tweets en la cola hasta que no queden más
while len(new_tweets) > 0 and len(alltweets) <= limit_number:
print ("getting tweets before" + str(oldest))
#en todas las peticiones siguientes usar el parámetro max_id para evitar duplicados
new_tweets = api.user_timeline(screen_name = screen_name,count=200,max_id=oldest)
#guardar los tweets descargados
alltweets.extend(new_tweets)
#actualizar el ID del tweet más antiguo menos 1
oldest = alltweets[-1].id - 1
#informar en la consola como vamos
print (str(len(alltweets)) + " tweets descargados hasta el momento")
#transformar los tweets descargados con tweepy en un arreglo 2D array que llenará el csv
outtweets = [(tweet.id_str, tweet.created_at, strip_undesired_chars(tweet.text),tweet.retweet_count,str(tweet.favorite_count)+'') for tweet in alltweets]
#escribir el csv
with open('%s_tweets.csv' % screen_name, "w", newline='') as f:
writer = csv.writer(f, quoting=csv.QUOTE_ALL)
writer.writerow(['id','created_at','text','retweet_count','favorite_count'''])
writer.writerows(outtweets)
pass
if __name__ == '__main__':
#especificar el nombre de usuario de la cuenta a la cual se descargarán los tweets
get_all_tweets("Agregar TwitterUser")
Ejecutar el script según se indica a continuación, esto creará un archivo llamado TwitterUser_tweets.csv
python3 tweets.py
Fuente original del código Aquí, se hicieron cambios para compatibilidad con Python 3, para garantizar que todas las columnas quedan entre “”, eliminar los saltos de línea de los tweets y los emoticones que pueden generar problemas al leer el archivo .csv resultante desde python.
Para cargar el archivo .csv en un Dataframe de Python
Continuamos con la temática de Ciencia de Datos para los Meetups de Women Who Code Medellín, este mes tratamos generación de datos aleatorios usando la librería Numpy de Python.
Reglas del juego que se presenta como ejemplo para ser resuelto simulando datos aleatorios para resolver la pregunta ¿Cuál es la probabilidad de Ganar este juego?
REGLAS
Se usa un dado para jugar, por lo cual los valores son de 1 a 6
Si tiramos 3 o menos devolvemos 1 peso al juego
Si tiramos más de 3 y hasta 5 nos dan 1 peso
Si tiramos 6, entonces tiramos de nuevo el dado y nos dan tantos pesos como el dado lo indique.
Jugamos con monedas, de modo que no hay valores de pesos negativos
El turno del jugador consiste en tirar el dado 100 veces
Se gana el juego si se obtiene más de 50 pesos al final del turno
Aquí el código que usamos en la presentación.
import numpy as np
import matplotlib.pyplot as plt
#Iniciar la semilla para garantizar que los datos serán iguales cada que se corra el algoritmo
np.random.seed(204)
todos_turnos = []
#Definir cuántas veces se corre la simulación
muestras = 600
for x in range(muestras) :
#Comenzar el turno sin monedas
monedas = 0
turno_aleatorio = [0]
for x in range(100) :
dado = np.random.randint(1,7)
if dado <= 3 :
monedas = max(0,monedas - 1)
elif dado < 6 :
monedas = monedas + 1
else :
monedas = monedas + np.random.randint(1,7)
#Registrar cuantas monedas tengo al final de cada tirada
turno_aleatorio.append(monedas)
#Guardar los resultados del turno
todos_turnos.append(turno_aleatorio)
#Formatear el arreglo como numpy array
np_todos_turnos = np.array(todos_turnos)
#Trasponer filas por columnas para adaptar a la gráfica
np_todos_turnos_t = np.transpose(np_todos_turnos)
#Sacar la última fila - resultado final de todos los turnos
ultimos = np_todos_turnos_t[-1,:]
#Calcular probabilidad de ganar contando los valores del vector
#mayores o iguales a 50 y dividiendo por el número de turnos
print('La probabilidad de ganar el juego es de ' + str(round(100*(ultimos >= 50).sum()/muestras,2)) + '%')
#Preparar la Gráfica del desarrollo de todos los turnos
plt.figure(200)
plt.xlabel('Cantidad lanzamientos del dado')
plt.ylabel('Monedas')
plt.title('Desarrollo de '+ str(muestras)+ ' turnos')
plt.plot(np_todos_turnos_t)
#Preparar la Gráfica de distribución de los turnos
plt.figure(300)
plt.xlabel('Total de monedas al final del turno')
plt.ylabel('Cantidad de turnos en el rango del total')
plt.title('Histograma para '+ str(muestras)+ ' turnos')
plt.hist(ultimos)
#Mostrar las gráficas
plt.show()
Les compartimos el hangout de Women Who Code Medellín de Abril, donde hablamos de carga de datos externos usando la librería Python de Pandas y realizando gráficos con ellos.
Con más detalle sobre graficación puedes ver el meetup de marzo.
Estamos en proceso de hacer meetups presenciales en la ciudad de Bogotá, les estaremos avisando.
Una vez hemos instalado Python y un IDE básico, comencemos a operar.
Operaciones sencillas como suma, división, entre otros. El tipo de una variable se define al momento de asignarle valor:
entero = 3 + 5
flotante = 5 / 13
#mostrar el resultado
print(entero)
#mostrar una operación
print(flotante + entero)
#imprimir tipo de variable
print(type(flotante))
#Asignar un string
texto = "Esto es el resultado de dos variables "
resultado = entero + flotante
#Imprimir textos y números
print(texto + str(resultado))
También podemos crear listas, los elementos pueden ser de diferente tipo.
sublista1 = [3, "pedro"]
#Hacer listas de listas
sublista2 = [5, "juan"]
lista = [sublista1, sublista2]
#O concatenar las listas
listaconcatenada = sublista1 + sublista2
#Las listas también pueden imprimirse
print(lista)
print(listaconcatenada)
Las listas no permiten hacer operaciones numéricas entre ellas, para ello necesitamos arreglos, que están dispuestos en la librería numpy.
#Importamos la librería y si lo deseamos le asignamos un nombre corto con "as"
import numpy as np
#Podemos crear listas comunes y llevarlas a arreglos
estatura = [1.55, 1.70, 1.80, 1.75, 1.60]
peso = [60.2, 67.5, 95.3, 50.3, 68.2]
np_estatura = np.array(estatura)
np_peso = np.array(peso)
#una vez son arreglos podemos hacer cálculos elemento a elemento
#**2 es elevar a la segunda potencia
bmi = np_peso / np_estatura**2
#Y mostrar el resultado, para este caso el índice de masa corporal
print(bmi)
Los arreglos solo permiten un único tipo de datos. Para extraer un dato recurrimos al índice del arreglo, recordar que inicia en cero.
print(estatura[1])
O usar una condición para extraerlo
#Buscar los BMI menores a 18.5, que es considerado bajo peso
condicion = bmi < 18.5
#Se obtiene un arreglo que indica cuáles posiciones cumplen o no la condición
print(condicion)
#Se usa este arreglo para extraer los resultados deseados.
print(bmi[condicion])
Podemos crear arreglos de N dimensiones, pero teniendo en cuenta que solo tendrán un único tipo de datos.
np_2dimensiones = np.array([peso, estatura])
#El tipo es numpy.ndarray
print(type(np_2dimensiones))
#Contiene 2 filas y 5 columnas
print(np_2dimensiones)
Para especificar elementos individuales usamos los índices: [fila][columna]
#Una sola fila
np_2dimensiones[0]
#Un solo elemento
np_2dimensiones[1][2]
Para especificar un subrango: [rango_fila, rango_columna] y produciremos la intersección de los rangos.
El signo “:” significa incluir todo el rango de fila o columna
Al especificar un rango el fin especificado estará una posición más allá del fin deseado, así inicio:fin + 1
Si queremos desde un inicio hasta el fin, así inicio:
#Una sola columna
np_2dimensiones[:,1:2]
numpy permite calcular algunas variables estadísticas, puedes explorar más en la documentación de Numpy.
También permite generar datos aleatorios, en este ejemplo generaremos datos redondeados a 2 cifras decimales, en una distribución normal, especificando la media, la desviación estándar y el número de muestras:
El instalador se ejecuta, para el caso de OSX por tratarse de un paquete no firmado mostrará un error, luego se debe ingresarse a Preferencias del Sistema -> Seguridad y privacidad. En la opción: “Permitir apps descargadas de” verá una advertencia por el paquete recién ejecutado, se autoriza que se ejecute y se procede a instalar.
OSX tiene una versión preinstalada (2.7), la versión que se descarga quedará instalada solo para el usuario y no afecta la versión del sistema operativo.
Para instalar el manejador de paquetes pip, se descarga el script get-pip.py desde una fuente confiable como https://bootstrap.pypa.io/get-pip.py una vez descargado se ejecuta:
python3 get-pip.py
Esto instalará las dependencias necesarias, tenga en cuenta que python3 se refiere a la versión instalada, si usa python solamente en el comando intentará hacerlo sobre la versión del sistema operativo y generará errores de permisos.
Una vez instalado pip para instalar nuevos paquetes en python, por ejemplo Numpy, usar el manejador de paquetes de este modo para instalar el paquete básico de computación científica en Python:
pip3 install numpy
Notar nuevamente el uso del comando como pip3 para que el sistema operativo ubique apropiadamente la versión con la cual se trabaja.
Seleccione el entorno de desarrollo de su preferencia, uno IDE sencillo para principiantes puede ser Thony, el cual puede descargarse de http://thonny.org
Para el trabajo con gráficas es importante instalar un paquete que pueda trazarlas.
pip3 install matplotlib
Otras librerías útiles para instalar:
Trabajo avanzado con fechas: dateutil
Uso de tablas de datos e importarlos desde csv: pandas
pip3 install python-dateutil
pip3 install pandas
Más sobre operaciones básicas con Python y uso de Numpy AQUÍ