#!/usr/bin/env python
# coding: utf-8

# # Análisis exploratorio de los datos

# ## Introducción

# Ya tenemos los datos limpios.  Ejecutamos un análisis exploratrio...
# 
# Al trabajar con datos numéricos, habitualmente obtenemos estadísticos comunes como valores medios o cómo se distribuyen los datos, sus valores más habituales, ... La idea al trabajar con textos es la misma. Buscaremos patrones obvios a través del análisis exploratorio para luego centrarnos en los patrones ocultos a través de Machine Learning. De cada uno de los textos extraidos, buscaremos:
# 
# 1. **Palabras más comunes** - localizarlas y crear un word cloud
# 2. **Total palabras únicas** - buscaremos las palabras únicas
# 3. **Total palabrotas**

# ## Palabras más comunes

# ### Análisis

# In[1]:


# Leemos el document-term matrix generado en el notebook previo
import pandas as pd

datos = pd.read_pickle('dtm.pkl')
datos = datos.transpose()
datos.head()


# In[2]:


# Localizamos el tpop 30 de las palabras usadas por cada cómico.
top_dict = {}
for c in datos.columns:
    top = datos[c].sort_values(ascending=False).head(30)
    top_dict[c]= list(zip(top.index, top.values))

top_dict


# In[3]:


# ¿Cuáles son las 15 palabras más dichas por cada cómico?
for comico, top_words in top_dict.items():
    print(comico)
    print(', '.join([word for word, count in top_words[0:14]]))
    print('---')


# **NOTA:** A través del resultado obtenido podríamos obtener las nubes de palabras, pero podemos ver que hay términos que aportan poco.  Estos términos pueden añadirse a las stopwords...
# 
# 

# In[4]:


# Extraeremos ahora el top 30 de cada cómico.
from collections import Counter

palabras = []
for comico in datos.columns:
    top = [palabras for (palabras, count) in top_dict[comico]]
    for t in top:
        palabras.append(t)
        
palabras


# In[5]:


# Obtenemos la frecuencia de aparición de cada palabra
Counter(palabras).most_common()


# In[6]:


# Si más de la mitad de los cómicos tienen alguna de estas palabras en su top, la eliminamos.
# De esta manera, eliminamos palabras comunes y nos centramos en las que caracterizan a cada cómico.
add_stop_words = [palabra for palabra, count in Counter(palabras).most_common() if count > 6]
add_stop_words


# In[10]:


# Actualizamos nuestro document-term matrix con la nueva lista de stop words
from sklearn.feature_extraction import text 
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer

# Cargamos los datos limpios generados previamente.
datos_limpios = pd.read_pickle('datos_limpios.pkl')

# Añadimos las nuevas stop words
stop_words = text.ENGLISH_STOP_WORDS.union(add_stop_words)

# Volvemos a generar el document-term matrix
cv = CountVectorizer(stop_words=stop_words)
datos_cv = cv.fit_transform(datos_limpios ['transcripcion'])
data_stop = pd.DataFrame(datos_cv.toarray(), columns=cv.get_feature_names())
data_stop.index = datos_limpios.index

# Guardamos en formato pickle para su uso más adelante (scritp 4).
import pickle
pickle.dump(cv, open("cv_stop.pkl", "wb"))
data_stop.to_pickle("dtm_stop.pkl")


# In[11]:


# Un poco de color.  Generamos algunas nubes de palabras.
# Desde un terminal Anaconda: conda install -c conda-forge wordcloud 
# ó
# !pip install wordcloud
from wordcloud import WordCloud

wc = WordCloud(stopwords=stop_words, background_color="white", colormap="Dark2",
               max_font_size=150, random_state=42)


# In[13]:


# Reset the output dimensions
import matplotlib.pyplot as plt

plt.rcParams['figure.figsize'] = [20, 8]

nombres_completos = ['Ali Wong', 'Anthony Jeselnik', 'Bill Burr', 'Bo Burnham', 'Dave Chappelle', 'Hasan Minhaj',
                     'Jim Jefferies', 'Joe Rogan', 'John Mulaney', 'Louis C.K.', 'Mike Birbiglia', 'Ricky Gervais']

# Subplot para cada cómico
for index, comico in enumerate(datos.columns):
    wc.generate(datos_limpios['transcripcion'][comico])
    
    plt.subplot(3, 4, index+1)
    plt.imshow(wc, interpolation="bilinear")
    plt.axis("off")
    plt.title(nombres_completos[index])
    
plt.show()


# ### Insigths

# * Ali Wong usa mucho la palabra shit y después la palabra husband.
# * Ricky Gervais usa principalmente 2 palabras y el resto tienen apariciones similares.
# * Muchos de los cómicos usan la palabra Fuck

# ## Número de palabras

# ### Analisis

# In[14]:


# Buscaremos ahora el total de palabras (sin repetir) por cómico y nos quedamos con aquellas palabras que aparezcan al menos una vez
lista_unicos = []
for comico in datos.columns:
    unicos = datos[comico].to_numpy().nonzero()[0].size
    lista_unicos.append(unicos)

# Creamos un dataframe con el resultado.
datos_palabras = pd.DataFrame(list(zip(nombres_completos, lista_unicos)), columns=['comico', 'palabras_unicas'])
datos_unicos_ordenado = datos_palabras.sort_values(by='palabras_unicas')
datos_unicos_ordenado


# In[15]:


# Calcularemos ahora el total de palabras pronunciadas por minuto por cada cómico.
# Los tiempos de cada actuación han sido:
# Ali Wong: 60
# Anthony Jeselnik: 59
# Bill Burr: 80
# Bo Burnham: 60
# Dave Chappelle: 67
# Hasan Minhaj: 73
# Jim Jefferies: 77
# Joe Rogan: 63
# John Mulaney: 62
# Louis C.K.: 58
# Mike Birbiglia: 76
# Ricky Gervais: 79

duracion_actuacion = [60, 59, 80, 60, 67, 73, 77, 63, 62, 58, 76, 79]

# Total de palabras usadas por cada cómico.
lista_total = []
for comico in datos.columns:
    totales = sum(datos[comico])
    lista_total.append(totales)
    
# Enriquecemos el set de datos con nuevas variables construidas
datos_palabras['palabras_totales'] = lista_total
datos_palabras['duracion_actuacion'] = duracion_actuacion
# palabras por minuto
datos_palabras['ppm'] = datos_palabras['palabras_totales'] / datos_palabras['duracion_actuacion']

# Ordenamos el dataset por el total de palabras por minuto
datos_palabras_ordenado = datos_palabras.sort_values(by='ppm')
datos_palabras_ordenado


# In[16]:


# Un poco más de color.  Ploteamos...

import numpy as np
y_pos = np.arange(len(datos_palabras))

plt.subplot(1, 2, 1)
plt.barh(y_pos, datos_unicos_ordenado['palabras_unicas'], align='center')
plt.yticks(y_pos, datos_unicos_ordenado.comico)
plt.title('# Palabras únicas', fontsize=20)

plt.subplot(1, 2, 2)
plt.barh(y_pos, datos_palabras_ordenado.ppm, align='center')
plt.yticks(y_pos, datos_palabras_ordenado.comico)
plt.title('# Número de palabras por minuto', fontsize=20)

plt.tight_layout()
plt.show()


# ### Insigths

# * **Vocabulario**
#    * Ricky Gervais y Bill Burr usan muchas palabras en su actuación.
# 
# 
# * **Palabras por minuto**
#    * Joe Rogan y Bill Burr son los que más rápido hablan
# 

# ## Total de palabrotas

# ### Analisis

# In[17]:


Counter(palabras).most_common()


# In[18]:


datos.transpose()[['fucking', 'fuck', 'shit']]


# In[19]:


# Extraemos las palabrotas
# Me quedo con las columnas del corpus con las palabrotas
datos_tmp = datos.transpose()[['fucking', 'fuck', 'shit']]

datos_palabrotas = pd.concat([datos_tmp['fucking'] + datos_tmp['fuck'], datos_tmp['shit']], axis=1)
datos_palabrotas.columns = ['fuck', 'shit']
datos_palabrotas


# In[21]:


# Representamos los datos en un scatter plot
plt.rcParams['figure.figsize'] = [10, 8]

for i, comico in enumerate(datos_palabrotas.index):
    x = datos_palabrotas.fuck.loc[comico]
    y = datos_palabrotas.shit.loc[comico]
    plt.scatter(x, y, color='blue')
    plt.text(x+1.5, y+0.5, nombres_completos[i], fontsize=10)
    plt.xlim(-5, 155) 
    
plt.title('# de palabrotas usadas', fontsize=20)
plt.xlabel('# de Fucks', fontsize=15)
plt.ylabel('# de Shits', fontsize=15)

plt.show()


# ## Ejercicios

# 1. ¿Qué otras palabras crees que podría ser interesante comparar?

# In[ ]:





# ## Análisis bigramas

# In[22]:


datos_limpios ['transcripcion']


# In[23]:


vectorizer = CountVectorizer(ngram_range = (2,2)) 
X1 = vectorizer.fit_transform(datos_limpios ['transcripcion'])  
features = (vectorizer.get_feature_names()) 
print("\n\nBigramas : \n", features) 
print("\n\nX1 : \n", X1.toarray()) 


# In[24]:


# Aplicando TFIDF 
vectorizer = TfidfVectorizer(ngram_range = (2,2)) 
X2 = vectorizer.fit_transform(datos_limpios ['transcripcion']) 
scores = (X2.toarray()) 
print("\n\nScores : \n", scores) 


# In[25]:


# Extraemos los bigramas Top
sums = X2.sum(axis = 0) 
data1 = [] 
for col, term in enumerate(features): 
    data1.append( (term, sums[0,col] )) 
ranking = pd.DataFrame(data1, columns = ['bigrama','rank']) 
words = (ranking.sort_values('rank', ascending = False)) 
print ("\n\nBigramas : \n", words.head(20)) 


# Tenemos los bigramas más habituales.  Ahora podríamos eliminar los que consideremos que no aportan a nuestro análisis como por ej. 'in the' o 'on the'.
# En este caso no eliminaremos ni bigramas ni trigramas.
