No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Refinamiento y visualización de cuerpos de texto

9/24
Recursos

Aportes 36

Preguntas 2

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Para lo de quitar las palabras que no generan valor yo suelo usar librerías que contienen listas de stopwords, dado que siento que haciéndolo por la longitud de la palabra igual podríamos estar perdiendo datos útiles

from nltk.corpus import stopwords

Excelente profesor.El poder de lo sencillo es propio de verdaderos conocedores.Muy bien estructurado el curso.Esta ventana de tecnología es asombrosa y completamente descrestante. El conocimiento se vuelve infinito y es una fantasía ver lo que ha sido capaz de desarrollar el hombre

a mi me funciono con este código para los strings. por si a alguien le sirve
dtypes = [(‘word’,object),(‘frequency’,int)]
palabras_interesantes_np = np.array(palabras_interesantes, dtype = dtypes)

Grafica lo mismo.

top_words = 20
palabras_interesantes = np.sort(palabras_interesantes, order = 'frecuency')[-top_words:]
x = palabras_interesantes['word']
y = palabras_interesantes['frecuency']
plt.figure(figsize=(10,5))
plt.plot(x,y)
plt.xticks(x,rotation='vertical')
plt.grid(True)
plt.show()```

¿Para qué usamos?:
top_words = 20
x = np.arange(len(palabras_interesantes[-top_words:]))
En vez de:
top_words = 20
x = np.arange(top_words)

import nltk

nltk.download('book')
nltk.download('stopwords')

from nltk.corpus import stopwords
from nltk.book import *

stop_words = stopwords.words('english')

from collections import Counter

import matplotlib.pyplot as plt
import numpy as np
import re

%matplotlib inline
def fdist(corpus):
    pattern = r'\w+(?:-\w+)*'
    search = re.compile(pattern)

    lower = [word.lower() for word in corpus]
    counts = Counter(lower)

    for word, count in counts.items():
        if not search.search(word):
            continue

        if word not in stop_words:
            yield word, count
dtypes = [('word', 'U15'), ('frequency', int)]
words = np.array( list(fdist(text1)), dtype=dtypes )
words = np.sort(words, order='frequency')[::-1]
n_words = 21
x, y = zip(*words[:n_words])

plt.figure(figsize=(12,5))

plt.plot(x, y)
plt.xticks(x, rotation=60)

plt.show()

No se si mas adelante en el curso lo realiza, pero pienso que una de las primeras cosas que se deberia realizar es colocar todas las palabras en mayúsculas o minúsculas

He creado lo que considero un mejor filtro, en lugar de usar solo la longitud de las palabras para descartarlas, he utilizado una lista de stopwords

interesting_words = [(w,fdist[w]) for w in set(text1) if re.search(r'[\w]+',w) and w not in stopwords.words('english') and fdist[w]>10 and len(w)>1]

Utilicé el método del profe y además stopwords ya que con solo stopwords me dejaba los puntos y corchetes, etc

from nltk.corpus import stopwords
stop_words = set(stopwords.words('english'))
long_words = [palabra for palabra in text1 if not palabra in stop_words]
long_words = [palabra for palabra in text1 if len(palabra) > 2]
long_words[:20]
['Moby',
 'Dick',
 'Herman',
 'Melville',
 '1851',
 'ETYMOLOGY',
 'Supplied',
 'Late',
 'Consumptive',
 'Usher',
 'Grammar',
 'School',
 'The',
 'pale',
 'Usher',
 'threadbare',
 'coat',
 'heart',
 'body',
 'and']

import nltk
nltk.download(‘stopwords’)

stop_words = set(stopwords.words(‘spanish’))

filtered_sentence = [w for w in text if not w.lower() in stop_words]

En el NLP podemos convertir cadenas de texto a tokens pero solo con eso traeremos también información que nada aporta al modelo, para ello debemos filtrar todos los caracteres especiales y palabras que no aporten.

  • Tamaño de cadena

    Uno de los métodos para filtrado es por la cantidad de caracteres que posee

    long_words  = [palabra for palabra in text1 if len(palabra)>5]
    vocabulario_filtrado = sorted(set(long_words))
    vocabulario_filtrado[:10]
    
  • Frecuencia

    También la frecuencia es un valor a tener en cuenta

    Podemos ahora construir una lista de tuplas, basados en los conteos ya pre-calculados de la funcion FreqDist, asi:

    fdist_filtrado = [(‘account’,2), (‘additional’,32), (‘advancing’,5)…]

    Luego podemos conveertir el objeto creado a formato de np.array de Numpypara podeer haceer un sort por palabras mas frecuentes.

    fdist_filtrado = np.array(fdist_filtrado, *arg)

    np.sort(fdist_filtado, *arg)=[(‘account’,2), (‘additional’,32), (‘advancing’,5)…]

    palabras_interesantes = [(palabra, fdist[palabra])  for palabra in set(text1) if len(palabra)>5 and fdist[palabra]>10]
    dtypes= [('word', 'S10'), ('frequency', int)]
    
    palabras_interesantes=  np.array(palabras_interesantes, dtype= dtypes)
    

    Esto le dara un orden según la frecuencia

    palabras_interesantes = np.sort(palabras_interesantes, order= 'frequency')
    palabras_interesantes
    
  • Graficar palabras mas interesantes

    top_words=20
    x= np.arange(len(palabras_interesantes[-top_words:]))
    y = [freq[1] for freq in palabras_interesantes[-top_words:]]
    
    plt.figure(figsize=(10,5))
    plt.plot(x,y)
    plt.xticks(x,[str(freq[0]) for freq  in palabras_interesantes[-top_words:]], rotation = 'vertical')
    plt.grid(True)
    plt.show()
    

Pueden quitar las palabras que no generan valor usando la libreria stopwords

from nltk.corpus import stopwords
stops = set(stopwords.words('english'))
print(stops)

Para obtener strings en formato unicode y no en bytes (‘b’…)

dtypes = [('word', 'U10'), ('frequency', int)]

Hay un pequeño detalle a contemplar. Si contamos solo con las palabras mayores a 5 caracteres en español por ejemplo dejamos palabras afuera como amor, malo, feo, lindo.
Es entendíble que es un ejercicio pero en este caso hay que tener en cuenta que las palabras_++ no se debe filtrar de esa manera++_

Saludos

Cuando ponemos una cantidad de 200 palabras, se observa la preferencia del autor a utilizar ciertas palabras.

Esta es una forma alternativa y yo considero mas legible

top_words = 20
# x seran las palabras e y = seran la cantidad de veces que aparecen
# x, y tienen que ser arrays para poder ser graficados
# con np.arrange(len... estamos crando un array de las longitudes de las palabras
# palabras_interesantes[-top_words:]['word']
# Esto creara un arreglo de numeros enteros de 0..top_words (top_words elementos)
x = np.arange(len(palabras_interesantes[-top_words:]))
# Esto me devuelve las frecuencias para cada x
y = palabras_interesantes[-top_words:]['frequency']

# Dimensionar la imagen
plt.figure(figsize=(10, 5))
plt.xticks (x, palabras_interesantes[-top_words:]['word'], rotation='vertical')
# Renderizar los valores
plt.plot (x,y)
# Colocar un grid de background
plt.grid(True)
# Finalmentem, mostrar el grafico
plt.show()
en mi caso el codigo que me sirvio fue este dtype = \[('palabra', 'U10'), ('frecuencia', int)]palabras\_interesantes\_array = (np.array(palabras\_interesantes, dtype=dtype))palabras\_interesantes\_array
El refinamiento del texto es un proceso clave en NLP que incluye limpieza, normalización, tokenización y la eliminación de stopwords. Tras esto, la visualización mediante gráficos de frecuencia, nubes de palabras y análisis de bigramas ayuda a extraer información significativa del texto.
`import matplotlib.pyplot as plt` `# Ya había efectuado la inversión del arreglo` `top_words = palabras_interes[:10]` `fig, ax = plt.subplots()ax.bar([word[0] for word in top_words], [word[1] for word in top_words])plt.xticks(rotation=45)` El gráfico: ![](https://static.platzi.com/media/user_upload/image-35c4b92c-04c1-4c62-8573-c104ea7500ce.jpg)
`# Ya había efectuado la inversión del arreglotop_words = palabras_interes[:10]` `fig, ax = plt.subplots()ax.bar([word[0] for word in top_words], [word[1] for word in top_words])plt.xticks(rotation=45)` Así quedo el gráfico: ![](https://static.platzi.com/media/user_upload/image-dd99564d-a100-4276-8506-eb90a4bb42e4.jpg)
Este profesor es uno de los mejores en Platzi! Felicitaciones!

Adjunto mi código comentado. Es una variante del código de la clase que hace más procesos de limpieza, espero les sea de utilidad.

from nltk.stem import WordNetLemmatizer
from nltk.corpus import stopwords
import matplotlib.pyplot as plt
from collections import Counter
from nltk.book import text1
import string
import re


def clean_corpus(corpus, sw, lem, min_words, most_common):
    """
    Limpia un corpus de texto aplicando diferentes filtros.

    Args:
        corpus (list): Corpus de texto a limpiar.
        sw (set): Conjunto de palabras vacías (stop words) a eliminar.
        lem (WordNetLemmatizer): Objeto lematizador de palabras.
        min_words (int): Mínimo número de palabras en una palabra filtrada.
        most_common (int): Número de palabras más comunes a extraer.

    Returns:
        tuple: Una tupla que contiene el diccionario de palabras filtradas y una lista de las palabras más comunes.
    """
    filtered_corpus = [word.lower() for word in corpus if word.lower() not in sw]
    filtered_corpus = [word for word in filtered_corpus if word not in string.punctuation]

    filtered_corpus = [word for word in filtered_corpus if len(word) > 5]
    filtered_corpus = [word for word in filtered_corpus if not re.match(r'\d', word)]
    filtered_corpus = [lem.lemmatize(word) for word in filtered_corpus]
    filtered_corpus = Counter(filtered_corpus)
    mc = filtered_corpus.most_common(most_common)
    elementos_filtrados = {clave: valor for clave, valor in filtered_corpus.items() if valor > min_words}

    return elementos_filtrados, mc


def plot_freq(elementos):
    """
       Grafica la frecuencia de las palabras en un diccionario.

       Args:
           elementos (list): Lista de tuplas que contienen palabras y sus frecuencias.
       """
    palabras = [elemento[0] for elemento in elementos]
    frecuencias = [elemento[1] for elemento in elementos]
    plt.plot(palabras, frecuencias)
    plt.xticks(rotation=90)
    plt.grid(True)
    plt.xlabel('Palabras')
    plt.ylabel('Frecuencia')
    plt.title('Frecuencia de palabras')
    plt.tight_layout()
    plt.savefig("i2.png")


if __name__ == '__main__':

    lemmatizer = WordNetLemmatizer()
    stop_words = set(stopwords.words('english'))
    vocabulario_filtrado, vocabulario_popular = clean_corpus(text1, stop_words, lemmatizer, 5, 20)
    print(vocabulario_filtrado)
    print(vocabulario_popular)
    plot_freq(vocabulario_popular)


Hice otra versión creo que es un poco más limpia, rápida y los resultados son más interesantes.

import nltk
nltk.download('book')
nltk.download('stopwords')

from nltk.book import text1
from nltk.text import Text
from nltk.corpus import stopwords

english_stopwords = stopwords.words("english")
filtered_text1 = Text(filter(lambda word: word.isalpha() and word.lower() not in english_stopwords, text1))
filtered_text1.vocab().plot(20)

para los que no se quieran complicar con el grafico

plt.figure(figsize=(11, 6))
plt.plot(
    palabras_interesantes['word'][-30:],
    palabras_interesantes['frequency'][-30:],
    marker='o',
    linestyle='--',
    alpha=0.9
)

plt.grid(True, alpha=0.4, linestyle='--', color='black', linewidth=0.6, axis='y', which='both', zorder=0)

plt.xticks(rotation=90)
plt.xlabel('Palabra')
plt.ylabel('Frecuencia')
plt.title('Las 30 palabras más frecuentes con más de 5 caracteres')


plt.show()

Dtypes le esta diciendo a numpy como interpretar esos objetos

Me gusta mucho el orden del notebook que publica en serio ahorra mucho tiempo , casi siempre voy y copio el texto

el codigo si lo hago para practicar

muchas gracias

para eliminar los signos de puntuación sin perder el información que pueda ser útil, empleo la siguiente función

import string
def remove_punctuation(value):
    result = ""
    for c in value:
      if c not in string.punctuation:
            result += c
    return result
data= remove_punctuation(data)
data

Un poquito mas de documentación por aqui :

fdist = FreqDist(text1) # https://www.kite.com/python/docs/nltk.FreqDist
fdist.most_common(20)   # 20 most common words occurrences in text
fdist.plot(20)          # draw a line chart with Y axis being amount of occurrences and X being the word
fdist['monster']        # as per a dicitionary return the value of that specific key

Interesante herramienta, ya lo veo utilizando un Scrapy para alimentar el Colab y hacer muchas interpretaciones de tendencias en la web!

Me gusta más mostrar los textos más usados en el libro y para eso es necesario agregar un parámetro adicional para rotar el texto:

top_words = 20
x = [element[0] for element in palabras_interesantes_2[-top_words:]]
print(x)
y = [element[1] for element in palabras_interesantes_2[-top_words:]]
print(type(y[0]))
print(y)
plt.figure(figsize=(10,5))
plt.plot(x,y)
plt.grid(True)
plt.xticks(rotation=90)
plt.show()

Esta buenisimo el curso, siempre vuelvo para aprender algo más,
Quizás me perdi en algo.
Como llego de un string -> una variable **nltk.text.Text **para poder hacer lo de frecuencia y conteo


texto = """ Cuando sea el rey del mundo  (imaginaba él en su cabeza) no tendré que  preocuparme por estas bobadas. 
            Era solo un niño de 7 años, pero pensaba que podría ser cualquier cosa que su imaginación le permitiera visualizar en su cabeza ..."""

pattern = r'''(?x)                 # set flag to allow verbose regexps
              (?:[A-Z]\.)+         # abbreviations, e.g. U.S.A.
              | \w+(?:-\w+)*       # words with optional internal hyphens
              | \$?\d+(?:\.\d+)?%? # currency and percentages, e.g. $12.40, 82%
              | \.\.\.             # ellipsis
              | [][.,;"'?():-_`]   # these are separate tokens; includes ], [
'''
a = nltk.regexp_tokenize(texto, pattern)

type(a) # list

gracias!

Que genial como se va complementando con cursos anteriores, ya todo va tomando más forma.

Excelente clase, excelente explicación de las herramientas

Un comentario sobre esta funcion:

[str(freq[0]) for freq in palabras_ordenadas[-top_words:]]

Lo unico que hace es que combierte el dato byte (b’word’) a string (" b’word’ ") la funcion correcta para convertir de bytes a string seria:

[bytes.decode(freq[0]) for freq in palabras_ordenadas[-top_words:]]

list(map(lambda word: bytes.decode(word), x))

En su defecto segun la documntacion de numpy acerca de los dtypes no es recomendable usar ‘S’ yo prefiero usar el dtype ‘U’ ya que este lo guarda como un string unicode directamente y no tenemos que estar haciendo transformaciones .


Supongo que ahora no importa mucho ya que solo estamos imprimiendo imformacion, pero yo supongo que afectara despues que querramos usar las palabras para otras operaciones

long_words = [palabra for palabra in text1 if len(palabra) > 5]
una observación, con esta logica tambien esta eliminando palabras que no sean mayor a 5, en este caso esta modificando palabras como moby, dick, late, etc, las cuales nos pueden servir mas adelante en el analisis y no se si vaya a afectar el desempeño del mismo.

una forma que encontre es con una function de NLTK que solamente selecciona las palabras.

long_words = [palabra for palabra in text1 if len(palabra) > 5]

ya despues eliminamos las stop_words del idioma ingles.

# List stop words
from nltk.corpus import stopwords
print(stopwords.words("english"))
# Remove stop words
words = [word for word in long_words2 if word not in stopwords.words("english")]

Eso si nuestra lista es mas grande que la que da usando el metodo de Francisco (55208) y con el metodo sugerido son 118820.

Saludos.

por alguna razon my google colab no encontraba el modulo fdist asi que tuve que reutilizar algunas funciones para poder sacar la lista de tuplas y poder plotear la data