#!/usr/bin/env python
# coding: utf-8
#
# # 006 - PyLadiesMadrid: Procesamiento del Lenguaje Natural
# ### **Claudia Guirao Fernández**
# _Data Scientist @ Kernel Analytics_
# Objetivos de hoy:
# * Introducir las herramientas y librerías de text mining y NLP en Python
# * Ver cómo se pueden realizar estas operaciones en Python
# * Descubrir con un corpus en Español algunas curiosidades interesantes sobre los Premios Goya al cine español
# ## 1. _Basics_ sobre string en Python
# In[1]:
mystring = '¡Hola Pyladies Madrid!'
mystring2 = "¡Hola 'Pyladies Madrid'!"
print(mystring2)
# In[2]:
print(str(len(mystring)) + ' longitud de la cadena')
print(str(mystring.index("o")) + ' posición') #primera ocurrencia
print(str(mystring.count("a")) + ' veces') #contar el número de ocurrencias
# In[3]:
print(mystring.upper())
print(mystring.lower())
# In[4]:
print(mystring[4])
print(mystring[1:5])
print(mystring[::-1])
# Más información: [Basic String Operations](https://www.learnpython.org/en/Basic_String_Operations)
# ## 2. Conceptos básicos al trabajar con texto
# * **corpus**: conjunto estructurado de textos / documentos
# * **stopwords**: es castellano "palabras vacías", se filtran de los análisis por su escaso aporte/significado
#
#
# **Normalizar**: el texto consiste en unificar la forma de los textos. Para ello hay distintas operaciones y algoritmos que pueden ayudarnos.
# 1. **tokenizar**: operación consistente en identificar las distintas unidades o tokens, en una frase identificamos las distintas palabras
# 2. **stemming**: consiste en reducir las palabras a su tema (Algoritmo de Porter, Snowball, entre otros)
# 3. **lematizar**: es un proceso lingüístico que consiste en, dada una forma flexionada (es decir, en plural, en femenino, conjugada, etc), hallar el lema correspondiente. El lema es la forma que por convenio se acepta como representante de todas las formas flexionadas de una misma palabra
#
# _¿Qué es mejor lematizar o hacer stemming? ¿qué algoritmos funcionan mejor?_
#
# Operaciones con el texto normalizado:
#
# * **TF**: Calcular la frecuencia de aparición de los términos en uno o varios documentos
# * **n-gramas**: conjuntos de n palabras que aparecen en el mismo documento
# * **TF-IDF**: frecuencia de término – frecuencia inversa de documento (o sea, la frecuencia de ocurrencia del término en la colección de documentos), es una medida numérica que expresa cuán relevante es una palabra para un documento en una colección
# ## 3. Librerías más comunes para el tratamiento de texto
# * [**NLTK**](https://www.nltk.org/): Librería principal para el procesamiento de texto en Python. Dispone de un [manual online](http://www.nltk.org/book/). Posee una interfaz sencilla y cubre la mayor parte de las operaciones. Fue la primera y es de las más extendidas.
# * [**Textblob**](http://textblob.readthedocs.io/en/dev/) : De nuevo cumple bastantes de las operaciones de procesamiento del lenguaje, está construida sobre NLTK y pretende ser más intuitiva que la ésta. Incluye un módulo de traducción y detección del idioma. [Ver tutorial](https://www.analyticsvidhya.com/blog/2018/02/natural-language-processing-for-beginners-using-textblob/) Es la segunda en velocidad por delante de NLTK.
# * [**SpaCy**](https://spacy.io): es la librería más reciente, su interfaz es muy fácil de utilizar. Posee bastantes modelos ya entrenados incluyendo _deep learning_
#
# _(las tres soportan multiples idiomas, quizá SpaCy es la más limitada porque lleva menos años disponible, aunque todas soportan el castellano)_
#
# * [**Gensim**](https://radimrehurek.com/gensim/): Complemento de las anteriores, especialmente centrada en el modelado de temática (LDA)
#
# ### ¿Cómo instalar las librerías?
# ```conda install -c conda-forge spacy```
#
# ```python -m spacy download es```
#
#
# ```conda install -c anaconda nltk```
# ```conda install -c anaconda gensim ```
# In[5]:
# nltk.download()
# ## 4. Let's play
# Importamos las librerías necesarias
# In[6]:
import numpy as np
import pandas as pd
from IPython.display import display, HTML
import nltk
import spacy
import gensim
import re
import os
import codecs
from sklearn import feature_extraction
import seaborn as sns
import matplotlib.pyplot as plt
# Cargamos el modelo en español para SpaCy
# In[7]:
import spacy
import es_core_news_sm
nlp = es_core_news_sm.load()
# Importamos el fichero de texto que contiene la sinopsis para las películas nominadas desde la edición 14 de los premios.
#
# Para obtener esta información he _escrapeado_ la web oficial de los [Premios Goya](premiosgoya.com)
# In[8]:
info_pelis = pd.read_csv("sinopsis_nominados_goya.csv",encoding='latin-1')
# Al hacer el scrapping de la web el texto contiene algunas cosas que nos gustaría eliminar antes de comenzar
# In[9]:
def clean_Goya(tit):
return(' '.join(tit.split()))
info_pelis['titulo'] = info_pelis.titulo.apply(clean_Goya)
info_pelis['descripcion'] = info_pelis.descripcion.apply(clean_Goya)
# Cargamos el fichero que contiene si las películas han sido nominadas o ganadoras en la categoría mejor película o mejor dirección y añadimos esas columnas a nuestro _dataframe_ original
# In[10]:
premios = pd.read_csv("titulo_edicion.csv", encoding='latin-1', sep=';')
info_pelis = pd.merge(info_pelis, premios[['titulo','edicion','nom_mejor_pelicula','gana_mejor_pelicula','nom_mejor_direc','gana_mejor_direc']], on = ['titulo', 'edicion'], how='inner')
info_nominadas = info_pelis[(info_pelis.nom_mejor_pelicula == 1) | (info_pelis.nom_mejor_direc==1)]
print(str(len(info_nominadas)) + ' peliculas nominadas a mejor película o a mejor dirección')
# In[11]:
display(info_pelis.head())
# Este es el tipo de información con la que vamos a trabajar:
# In[12]:
print(info_nominadas.iloc[0].titulo)
print('............')
print(info_nominadas.iloc[0].descripcion)
# In[13]:
print(info_nominadas.iloc[1].titulo)
print('............')
print(info_nominadas.iloc[1].descripcion)
# ### Entidades
# Vamos a localizar entidades mediante SpaCy, de una forma muy sencilla.
# In[14]:
doc = nlp(info_nominadas.iloc[1].descripcion)
print([(w.text, w.pos_) for w in doc])
# También es posible visualizar esta información y las relaciones entre términos mediante **displacy**
#
# In[15]:
# from spacy import displacy
# displacy.serve(doc, style='dep')
# Para cada documento SpaCy nos ofrece mucha otra información:
# In[16]:
mytokens = []
for token in doc:
mytokens.append({'text': token.text, 'lemma': token.lemma_, 'pos': token.pos_,'tag':token.tag_,'dep':token.dep_,
'shape':token.shape_, 'is_alpha': token.is_alpha, 'is_stop': token.is_stop})
pd.DataFrame(mytokens)
# ### Stopwords
# _¿Qué entendemos por palabras vacías?_
# Cargamos las stopwords predefinidas en español en NLTK
# In[17]:
stopwords_spa = nltk.corpus.stopwords.words('spanish')
print(len(stopwords_spa))
print(stopwords_spa[0:21])
# Idéntica operación en SpaCy
# In[18]:
from spacy.lang.es.stop_words import STOP_WORDS
print(len(STOP_WORDS))
print(list(STOP_WORDS)[0:21])
# Como primera operación vamos a calcular la frecuencia en la que aparece cada término. Excluyendo aquellos que son stopwords, nombres propios o particulas
# In[20]:
from __future__ import print_function, unicode_literals
import spacy
from collections import defaultdict, Counter
pos_counts = defaultdict(Counter)
words = []
for sinop in info_pelis.descripcion:
doc = nlp(sinop)
for token in doc:
if token.is_stop != True and token.is_punct != True and token.pos_ not in ['PROPN', 'CONJ', 'ADP', 'DET']:
words.append(token.lemma_)
word_TF = Counter(words)
word_TF = pd.DataFrame.from_dict(word_TF, orient='index').reset_index()
word_TF = word_TF.rename(index=str, columns={"index": "token", 0: "TF"})
word_TF = word_TF.sort('TF', ascending=False)
# Las 10 palabras más frecuentes son:
# In[21]:
display(word_TF.head(10))
# In[29]:
display(word_TF[word_TF.token.isin(['cine', 'director', 'español', 'película', 'vida',
'vivir', 'mujer', 'hombre', 'joven', 'hijo', 'madre', 'padre'])])
# En el contexto en el que estamos trabajando conviene añadir algunas otras palabras muy comunes en las sinopsis
# In[69]:
MY_STOP_WORDS = STOP_WORDS.copy()
MY_STOP_WORDS = MY_STOP_WORDS.union(['cine','actor','director','español','película','documental','historia',
'vida','vivir','año','vivir', 'mujer', 'hombre', 'joven', 'hijo', 'madre',
'padre', 'niño','niña', 'hijo', 'hija' ])
# ### Stemmers y lematizadores
# NLTK ofrece distintos _stemmers_ y _lemmatizers_ con un rendimiento desigual en español:
# 1. Cargamos uno de los stemmer de NLTK: [SnowballStemmer](https://snowballstem.org/algorithms/spanish/stemmer.html)
# In[70]:
from nltk.stem.snowball import SnowballStemmer
stemmer_eng = SnowballStemmer("english")
stemmer = SnowballStemmer("spanish")
# In[71]:
print(stemmer_eng.stem('girls'))
print(stemmer.stem('chicas'))
# In[72]:
from nltk.stem import WordNetLemmatizer
wordnet_lemmatizer = WordNetLemmatizer()
print(wordnet_lemmatizer.lemmatize('girls'))
print(wordnet_lemmatizer.lemmatize('chicas'))
# En SpaCy sólo se han desarrollado lematizadores, aquí un interesante hilo en GitHub [Built-in stemmer?](https://github.com/explosion/spaCy/issues/327)
# In[73]:
doc = nlp('chica')
for token in doc:
print(token.lemma_.lower())
# ## 5. Clustering (NLTK, SpaCy, Sklearn)
# En este apartado vamos a tratar de identificar segmentos de películas agrupando mediante las sinopsis. Esta operación puede apoyarse tanto en las funciones disponibles en NLTK como en SpaCy.
# ### 5.1. Funciones para tokenizar y lematizar.
# Funciones con NLTK
# In[74]:
def tokenize_and_stem(text):
# Primero se extraen los tokens de una frase, despues se extraen las palabras,
# para asegurar que la puntuación toma su propio tokent
tokens = [word for sent in nltk.sent_tokenize(text) for word in nltk.word_tokenize(sent)]
filtered_tokens = []
# Solo tomamos los tokens que contienen letras, para evitar tokens numericos y puntuacion
for token in tokens:
if re.search('[a-zA-Z]', token):
filtered_tokens.append(token)
stems = [stemmer.stem(t) for t in filtered_tokens] # se extrae el tema para cada palabra
return stems
def tokenize_only(text):
tokens = [word.lower() for sent in nltk.sent_tokenize(text) for word in nltk.word_tokenize(sent)]
filtered_tokens = []
for token in tokens:
if re.search('[a-zA-Z]', token):
filtered_tokens.append(token)
return filtered_tokens
# Funciones son SpaCy
# In[75]:
def tokenize_and_lemm_spacy(text):
doc = nlp(text)
lemmas = []
for token in doc:
if token.is_stop== False: # aprovechamos para eliminar ya las stopwords
if token.is_alpha== True: # Nos quedamos solo con los tokens que contienen letras
if token.pos_ not in ['PROPN', 'CONJ', 'ADP', 'DET']: # eliminamos nombres propios, conjunciones, determinantes
lemmas.append(token.lemma_.lower())
return lemmas
def tokenize_only_spacy(text):
doc = nlp(text)
tokens = []
for token in doc:
if token.is_stop== False :
if token.is_alpha== True:
if token.pos_ not in ['PROPN', 'CONJ', 'ADP', 'DET']:
tokens.append(token.text.lower())
return tokens
# In[76]:
print(info_nominadas.iloc[1].descripcion)
print(tokenize_only(info_nominadas.iloc[1].descripcion))
print(tokenize_and_stem(info_nominadas.iloc[1].descripcion))
# In[77]:
print(info_nominadas.iloc[1].descripcion)
print(tokenize_only_spacy(info_nominadas.iloc[1].descripcion))
print(tokenize_and_lemm_spacy(info_nominadas.iloc[1].descripcion))
# ### 5.2. Análisis sobre nuestro corpus
# Vamos a crear una lista con todas nuestras sinopsis
# In[78]:
synopses = list(info_pelis['descripcion'])
# Así como una lista de todos los términos encontrados:
# In[79]:
totalvocab_stemmed = []
totalvocab_tokenized = []
for i in synopses:
allwords_stemmed = tokenize_and_lemm_spacy(i)
totalvocab_stemmed.extend(allwords_stemmed)
allwords_tokenized = tokenize_only_spacy(i)
totalvocab_tokenized.extend(allwords_tokenized)
# Con estas dos listas, de tokens y lemas, vamos a crear un DataFrame, que contendrá el lema y en el índice el token. Así podemos rescatar en cualquier momento el token original.
# In[80]:
vocab_frame = pd.DataFrame({'words': totalvocab_tokenized}, index = totalvocab_stemmed)
print( str(vocab_frame.shape[0]) + ' en el vocab_frame')
# In[81]:
vocab_frame.head(10)
# A continuación definimos los parametros para la función de frecuencia inversa (tf-idf), para poder convertir la lista de sinopsis en una matriz de términos y documentos.
#
# Para alcanzar esta matriz, en primer lugar contamos el número de veces que ocurre una palabra en un documento. Así obtenemos una matriz de términos documentos.
#
# A continuación esta matriz es ponderada por la frecuencia inversa: palabras que ocurren frecuentemente en un documento pero no en el corpus reciben un peso mayor, asumiendo que aportan un mayor significado en el documento.
#
# Sobre los parámetros:
# * **max_df**: Es la máxima frecuencia dentro de los documentos que un _feature_ dado puede ser utilizado en la matriz tfi-idf. Si fijamos aquí un umbral mayor al 80% probablemente contenga poco significado, al menos en el contexto de este análisis.
# * **min_idf**: Puede tomar un porcentaje o un entero. Por ejemplo 3, en ese caso debe aparecer al menos 3 documentos para ser considerado.
# * **ngram_range**: Vamos a fijarnos solo en unigramas, no en bigramas o trigramas
# In[82]:
from sklearn.feature_extraction.text import TfidfVectorizer
#define vectorizer parameters
tfidf_vectorizer = TfidfVectorizer(max_df=0.8, max_features=200000,
min_df=3, stop_words=MY_STOP_WORDS,
use_idf=True, tokenizer=tokenize_and_lemm_spacy, ngram_range=(1,3))
get_ipython().run_line_magic('time', 'tfidf_matrix = tfidf_vectorizer.fit_transform(synopses) #fit the vectorizer to synopses')
print(tfidf_matrix.shape)
# _terms_ contiene la lista de features con la que vamos a realizar el cluster
# In[83]:
terms = tfidf_vectorizer.get_feature_names()
# Calculamos la distancia como 1- similaridad coseno, esto es la medida de similaridad entre nuestros documentos. La resta nos permitirá representarlo en el plano
# In[84]:
from sklearn.metrics.pairwise import cosine_similarity
dist = 1 - cosine_similarity(tfidf_matrix)
# ### 5.3. Clustering
# In[85]:
from sklearn.cluster import KMeans
num_clusters = 3
km = KMeans(n_clusters=num_clusters)
get_ipython().run_line_magic('time', 'km.fit(tfidf_matrix)')
clusters = km.labels_.tolist()
# In[86]:
from sklearn.externals import joblib
#Salvamos nuestro modelo, o bien lo cargamos si ya lo hemos ejecutado previamente
joblib.dump(km, 'doc_cluster.pkl')
#km = joblib.load('doc_cluster.pkl')
clusters = km.labels_.tolist()
# Construimos un pandas dataframe para que sea más cómodo trabajar
# In[87]:
films = {'title': list(info_pelis.titulo),
'synopsis': list(info_pelis.descripcion),
'edition': list(info_pelis.edicion),
'cluster': clusters,
'nom_mejor_pelicula': list(info_pelis.nom_mejor_pelicula),
'nom_mejor_dire': list(info_pelis.nom_mejor_direc),
'gana_mejor_pelicula': list(info_pelis.gana_mejor_pelicula)}
frame = pd.DataFrame(films, index = [clusters] , columns = ['title', 'synopsis', 'edition', 'cluster', 'nom_mejor_pelicula','nom_mejor_dire', 'gana_mejor_pelicula'])
# In[88]:
distribution_clusters = frame[['cluster', 'title']].groupby('cluster').count().reset_index() #numero de peliculas por cluster
distribution_clusters_nom = frame[frame.nom_mejor_pelicula==1][['cluster', 'title']].groupby('cluster').count().reset_index() #numero de peliculas nominadas a mejor pelicula por cluster
# Exploramos el resultado de la clusterización
# In[89]:
sns.set_style("whitegrid")
ax = sns.barplot(x="cluster", y="title", data=distribution_clusters)
ax.set(ylabel='# películas', xlabel='Cluster')
ax.set_title('Clusters de películas nominadas a los Goya')
plt.show()
plt.close()
# In[90]:
sns.set_style("whitegrid")
ax = sns.barplot(x="cluster", y="title", data=distribution_clusters_nom)
ax.set(ylabel='# películas', xlabel='Cluster')
ax.set_title('Clusters de películas nominadas a mejor película en los Goya')
plt.show()
plt.close()
# In[95]:
print('Cluster 0: ')
print(list(frame[(frame.cluster==0) & (frame.nom_mejor_pelicula ==1)].title))
print('Cluster 1: ')
print(list(frame[(frame.cluster==1) & (frame.nom_mejor_pelicula ==1)].title))
print('Cluster 2: ')
print(list(frame[(frame.cluster==2) & (frame.nom_mejor_pelicula ==1)].title))
# In[96]:
# sólo las películas nominadas a mejor película
frame_nom = frame[frame.nom_mejor_pelicula==1]
# In[97]:
over_edition = frame[['edition', 'cluster', 'title']].groupby(['edition', 'cluster']).count().reset_index()
# In[98]:
sns.set_style("whitegrid")
ax = sns.barplot(x="edition", y="title", hue="cluster", data=over_edition)
ax.set(ylabel='# películas', xlabel='Edición Premios Goya')
ax.set_title('Cluster de películas nominadas a los Goya')
plt.show()
plt.close()
# In[99]:
sns.set_style("whitegrid")
ax = sns.barplot(x="edition", y="title", hue="cluster", data=frame[frame.nom_mejor_pelicula==1][['edition', 'cluster', 'title']].groupby(['edition', 'cluster']).count().reset_index())
ax.set(ylabel='# películas', xlabel='Edición Premios Goya')
ax.set_title('Cluster de películas nominadas a los Goya en la candidatura Mejor Película')
plt.show()
plt.close()
# In[100]:
# nominadas en cada cluster y pct de ganadoras del premio Goya a mejor película
frame_nom[['cluster', 'gana_mejor_pelicula']].groupby(['cluster']).agg(['count', 'sum', 'mean']).reset_index()
# #### ¿Cuáles son los términos que hay detrás del clúster?
# In[101]:
from __future__ import print_function
# frame.index = range(len(frame.index))
print("Palabras top por cluster:")
print()
order_centroids = km.cluster_centers_.argsort()[:, ::-1]
for i in range(num_clusters):
print("Palabras Cluster %d :" % i, end='')
for ind in order_centroids[i, :26]: #15 palabras por cluster
print(' %s' % str(vocab_frame.ix[terms[ind].split(' ')].values.tolist()[0][0]), end=',')
print()
print()
# print("Cluster %d titles:" % i, end='')
# for title in frame.ix[i]['title'].values.tolist():
# print(' %s,' % title, end='')
# print() #add whitespace
# print() #add whitespace
# In[102]:
import os # for os.path.basename
import matplotlib.pyplot as plt
import matplotlib as mpl
from sklearn.manifold import MDS
MDS()
# Convertimos el resultado en 2 componentes para poder representarlo
mds = MDS(n_components=2, dissimilarity="precomputed", random_state=1)
pos = mds.fit_transform(dist) # shape (n_components, n_samples)
xs, ys = pos[:, 0], pos[:, 1]
# In[105]:
#set up colors per clusters using a dict
cluster_colors = {0: '#1b9e77', 1: '#d95f02', 2: '#7570b3', 3: '#e7298a', 4: '#66a61e'}
#set up cluster names using a dict
cluster_names = {0: 'Familia y costumbrismo',
1: 'Amor y aventura',
2: 'Histórico, sucesos y acción '
}
# In[106]:
get_ipython().run_line_magic('matplotlib', 'inline')
#crear dataframe, con los resultados de la descomposicion y otra información
df = pd.DataFrame(dict(x=xs, y=ys, label=clusters, title=list(frame.title),
nom_mejor_pelicula = list(frame.nom_mejor_pelicula),
gana_mejor_pelicula = list(frame.gana_mejor_pelicula),
))
df = df[df.nom_mejor_pelicula==1]
df.index = range(len(df.index))
#agrupamos por cluster
groups = df.groupby('label')
fig, ax = plt.subplots(figsize=(17, 9)) # set size
ax.margins(0.05) # Optional, just adds 5% padding to the autoscaling
for name, group in groups:
ax.plot(group.x, group.y, marker='o', linestyle='', ms=12,
label=cluster_names[name], color=cluster_colors[name],
mec='none')
ax.set_aspect('auto')
ax.tick_params(\
axis= 'x',
which='both',
bottom='off',
top='off',
labelbottom='off')
ax.tick_params(\
axis= 'y',
which='both',
left='off',
top='off',
labelleft='off')
ax.legend(numpoints=1)
for i in range(len(df)):
ax.text(df.ix[i]['x'],
df.ix[i]['y'],
df.ix[i]['title'], size=10)
plt.show()
plt.close()
# ### 5.4. Clustering jerárquico
# El [método Ward](https://es.wikipedia.org/wiki/Método_de_Ward) es un algoritmo de clustering jerárquico. Nos permite en cada etapa identificar el par de clusters con la mínima distancia. Para realizarlo emplearemos la distancia previamente calculada.
#
# Devuelve 2 clusters principales, reemplazando a los 5 anteriores
# In[107]:
from scipy.cluster.hierarchy import ward, dendrogram
linkage_matrix = ward(dist) #define the linkage_matrix using ward clustering pre-computed distances
fig, ax = plt.subplots(figsize=(15, 20))
ax = dendrogram(linkage_matrix, orientation="right", labels=list(info_pelis.titulo));
plt.tick_params(\
axis= 'x',
which='both',
bottom='off',
top='off',
labelbottom='off')
plt.tight_layout()
plt.savefig('ward_clusters.png', dpi=500)
plt.close()
#
# ## 6. Topic modelling
# Latent Dirichlet Allocation (LDA) es un modelo generativo que permite que conjuntos de observaciones puedan ser explicados por grupos no observados que explican por qué algunas partes de los datos son similares. Por ejemplo, si las observaciones son palabras en documentos, presupone que cada documento es una mezcla de un pequeño número de categorías (también denominados como tópicos/temas) y la aparición de cada palabra en un documento se debe a una de las categorías a las que el documento pertenece.
#
# In[108]:
import string
def strip_proppers(text):
# first tokenize by sentence, then by word to ensure that punctuation is caught as it's own token
tokens = [word for sent in nltk.sent_tokenize(text) for word in nltk.word_tokenize(sent) if word.islower()]
return "".join([" "+i if not i.startswith("'") and i not in string.punctuation else i for i in tokens]).strip()
# In[109]:
def strip_proppers_spacy(text):
token_list = []
doc = nlp(text)
for token in doc:
if token.is_stop == False and token.is_alpha == True and token.pos_ not in ['PROPN', 'CONJ', 'ADP', 'DET']:
token_list.append(token.text.lower())
return ' '.join(token_list)
# In[110]:
from nltk.tag import pos_tag
def strip_proppers_POS(text):
tagged = pos_tag(text.split())
non_propernouns = [word for word,pos in tagged if pos != 'NNP' and pos != 'NNPS']
return non_propernouns
# In[111]:
from gensim import corpora, models, similarities
#quitar los nombres propios
get_ipython().run_line_magic('time', 'preprocess = [strip_proppers_spacy(doc) for doc in synopses]')
#tokenizar
get_ipython().run_line_magic('time', 'tokenized_text = [tokenize_and_lemm_spacy(text) for text in preprocess]')
#quitar las stopwords
get_ipython().run_line_magic('time', 'texts = [[word for word in text if word not in MY_STOP_WORDS] for text in tokenized_text]')
# In[112]:
#crear un diccionario de Gemsim a partir de los documentos
dictionary = corpora.Dictionary(texts)
#quitar los extremos ( similar al min max fijado en el tf-idf)
dictionary.filter_extremes(no_below=1, no_above=0.8)
#convertir el diccionario en 'bag of words corpus' para usarlo como referencia
corpus = [dictionary.doc2bow(text) for text in texts]
# In[113]:
get_ipython().run_line_magic('time', 'lda = models.LdaModel(corpus, num_topics=3, id2word=dictionary, update_every=5, chunksize=10000, passes=100)')
# In[114]:
lda.show_topics()
# # REFERENCIAS
# * [NLTK book](http://www.nltk.org/book/)
# * [SpaCy 101](https://spacy.io/usage/spacy-101)
# * [SpaCy tutorial](https://www.analyticsvidhya.com/blog/2017/04/natural-language-processing-made-easy-using-spacy-%E2%80%8Bin-python/)
# * [Textblob](https://www.analyticsvidhya.com/blog/2018/02/natural-language-processing-for-beginners-using-textblob/)
# * [NLP essential](https://www.analyticsvidhya.com/blog/2017/10/essential-nlp-guide-data-scientists-top-10-nlp-tasks/)
# * [Document clustering](http://brandonrose.org/clustering)
#
#
# # ¡¡¡GRACIAS POR VUESTRA ATENCIÓN!!!!
# [PANDAS DOCUMENTATION SPRINT](https://www.meetup.com/es/PyData-Madrid/events/247525766/?eventId=247525766)
#