Open In Colab

Notebook diseñada para el Laboratorio de investigaciones en Humanidades Digitales - CONICET sobre el texto Viaje al Río de la Plata de Ulrico Schmidel¶

Por Romina De León (CONICET)¶

Esta notebook tiene como objetivo trabajar sobre el texto en formato plano realizado para el proyecto Viaje al Río de la Plata de Ulrico Schmidel. Con este se buscó generar visualizaciones del análisis textual, así como en las relaciones entre personajes, pueblos originarios en los trayectos y episodios de esta crónica. Para ello se utilizaron diversas librerías de Spacy, NLTK, Pandas, MatPlot, Seaborn, entre otras, y se realizará una sucinta descripción a lo largo del código sobre cada una de ellas.

Instalación y llamado de librerías y módulos¶

In [9]:
!pip install spacy """ librería SpaCy útil para análisis textual """

!pip install networkx matplotlib """ librería para generar visualizaciones estáticas, animadas e interactivas """
ERROR: Invalid requirement: '" librería SpaCy útil para análisis textual "': Expected package name at the start of dependency specifier
    " librería SpaCy útil para análisis textual "
    ^
ERROR: Invalid requirement: '" librería para generar visualizaciones estáticas, animadas e interactivas "': Expected package name at the start of dependency specifier
    " librería para generar visualizaciones estáticas, animadas e interactivas "
    ^
In [8]:
!python -m spacy download es_core_news_lg """ Descarga del modelo de entrenamiento y procesado de textos para el español, md indica modelo de tamaño mediano """
ERROR: Invalid requirement: '" Descarga del modelo de entrenamiento y procesado de textos para el español, md indica modelo de tamaño mediano "': Expected package name at the start of dependency specifier
    " Descarga del modelo de entrenamiento y procesado de textos para el español, md indica modelo de tamaño mediano "
    ^
In [3]:
#Librerías y módulos para generar visualizaciones

import matplotlib.pyplot as plt
import seaborn as sns

Carga de texto¶

In [10]:
# Cargamos el texto desde GitHub
#Requests librería para importar url
import requests

#función para descardar desde una url y con advertencia si existe error en el sitio web
def download_text_from_url(url):
    try:
        response = requests.get(url)
        response.raise_for_status()  # Excepciones por error de acceso
        return response.text
    except requests.exceptions.RequestException as e:
        print(f"Error de descarga de la URL: {e}")
        return None

url = "https://raw.githubusercontent.com/hdlabconicet/viaje-al-rio-de-la-plata/refs/heads/main/assets/downloads/schmidel.txt"
ulrico_txt = download_text_from_url(url)

if ulrico_txt:
    print(ulrico_txt[:100])

else:
    print("Error al tratar de descargar el archivo") #advertencia que no se puedo descargar el archivo
Viaje al Río de la Plata (1534-1554)
Urich Schmidel

Buenos Aires, Alsina 500
Cabaut y Cía. Edit

Para proceder con el análisis textual trabajaremos en el archivo de texto plano de la obra de Ulrico Schmidel, generado desde los archivos codificados en TEI-XML, para que no hubieses diferencias entre ambos.

Limpieza y tokenización del texto¶

A las palabras vacías, stopwords, generales del idioma español se añadieron las más frecuentes que se pueden considerar a una primera vista del texto, denominadas 'stopwords del siglo XVI'.

In [11]:
import re
import nltk
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize

# Recursos de NLTK, Natural Language Toolkit, librería que permite el procesamiento de lenguaje natural, con los modelos corpus y tokenize, se permite la descarga de palabras vacías y un separador en tokens de textos
nltk.download('punkt')
nltk.download('stopwords')
nltk.download('punkt_tab')
[nltk_data] Downloading package punkt to
[nltk_data]     C:\Users\Adm\AppData\Roaming\nltk_data...
[nltk_data]   Package punkt is already up-to-date!
[nltk_data] Downloading package stopwords to
[nltk_data]     C:\Users\Adm\AppData\Roaming\nltk_data...
[nltk_data]   Package stopwords is already up-to-date!
[nltk_data] Downloading package punkt_tab to
[nltk_data]     C:\Users\Adm\AppData\Roaming\nltk_data...
[nltk_data]   Package punkt_tab is already up-to-date!
Out[11]:
True
In [12]:
# Stopwords para el español del siglo XVI, tal vez podría ampliarse más
stopwords_siglo_XVI = set({
    'aquel', 'sino', 'aun', 'así', 'à', 'á', 'i', 'o', 'ó', 'ò', 'aquella', 'aquelos', 'aquelas', 'hast', 'dende', 'dixo', 'dixeron', 'dixieron', 'assí', 'assi', 'desque', 'después', 'allí', 'día'
})

# Stopwords estándar y del siglo XVI
nltk_stopwords = set(stopwords.words('spanish'))
stopwords_completas = nltk_stopwords.union(stopwords_siglo_XVI)

# Función de limpieza del texto, se utiliza expresiones regulares para encontrar y eleminar determinadas cadenas de caracteres
def limpiar_texto(texto):
    texto = re.sub(r"[^a-zA-ZáéíóúÁÉÍÓÚñÑüÜ\s]", "", texto, flags=re.UNICODE)
    palabras = texto.lower().split()
    palabras_filtradas = [palabra for palabra in palabras if palabra not in stopwords_completas] #se filtran las palabras que coinciden con stopwords
    return " ".join(palabras_filtradas)

# Función para limpiar y tokenizar
def clean_and_tokenize(text):
    # Eliminar caracteres especiales y tokenizar
    tokens = word_tokenize(re.sub(r'[^a-zA-ZáéíóúÁÉÍÓÚñÑüÜ]', ' ', text.lower()))
    # Filtrar stopwords
    tokens = [word for word in tokens if word not in stopwords_completas]
    return tokens
In [13]:
#carga de texto para limpieza
text = ulrico_txt
texto_limpio = limpiar_texto(text)

# Guarda el texto limpio
with open('texto_limpio.txt', 'w', encoding='utf-8') as file:
    file.write(texto_limpio)

print("Archivo 'texto_limpio.txt' creado exitosamente.")
print(texto_limpio[:100])
Archivo 'texto_limpio.txt' creado exitosamente.
viaje río plata urich schmidel buenos aires alsina cabaut cía editores librería colegio capítulo nav
In [14]:
texto = ulrico_txt
# Aplicar la función clean_and_tokenize
tokens = clean_and_tokenize(texto)

# Guardar los tokens en un archivo (como texto o como lista)
with open("ulrico_tokens.txt", "w", encoding="utf-8") as archivo_salida:
    archivo_salida.write(" ".join(tokens))  # Los tokens se guardan como texto

print("Tokens guardados en 'ulrico_tokens.txt'.")
print(tokens[:25])
Tokens guardados en 'ulrico_tokens.txt'.
['viaje', 'río', 'plata', 'urich', 'schmidel', 'buenos', 'aires', 'alsina', 'cabaut', 'cía', 'editores', 'librería', 'colegio', 'capítulo', 'navegación', 'amberes', 'españa', 'primer', 'lugar', 'haber', 'partido', 'andorf', 'amberes', 'llegué', 'días']
In [15]:
import nltk
from nltk.tokenize import word_tokenize
from nltk import pos_tag
import nltk
import spacy
import pandas as pd

nltk.download('punkt')  # Recursos para la tokenización
nltk.download('averaged_perceptron_tagger')  # Modelo para el etiquetado POS
# Cargar el modelo en español de spaCy
nlp = spacy.load("es_core_news_lg")
[nltk_data] Downloading package punkt to
[nltk_data]     C:\Users\Adm\AppData\Roaming\nltk_data...
[nltk_data]   Package punkt is already up-to-date!
[nltk_data] Downloading package averaged_perceptron_tagger to
[nltk_data]     C:\Users\Adm\AppData\Roaming\nltk_data...
[nltk_data]   Package averaged_perceptron_tagger is already up-to-
[nltk_data]       date!
In [16]:
# Procesamiento con SpaCy
doc = nlp(texto)

# lista de tuplas (palabra, etiqueta POS)
datos = [(token.text, token.pos_) for token in doc]

# Conversión de la lista en un dataframe
df = pd.DataFrame(datos, columns=["Palabra", "Etiqueta_POS"])

# Guardado del DataFrame en CSV
df.to_csv("etiquetas_pos_ulrico.csv", index=False, encoding="utf-8")

print("Archivo CSV generado con éxito: etiquetas_pos_ulrico.csv")

print(df.head(20))
Archivo CSV generado con éxito: etiquetas_pos_ulrico.csv
      Palabra Etiqueta_POS
0       Viaje        PROPN
1          al          ADP
2         Río        PROPN
3          de          ADP
4          la          DET
5       Plata        PROPN
6           (        PUNCT
7   1534-1554         NOUN
8           )        PUNCT
9        \r\n        SPACE
10      Urich        PROPN
11   Schmidel        PROPN
12   \r\n\r\n        SPACE
13     Buenos        PROPN
14      Aires        PROPN
15          ,        PUNCT
16     Alsina        PROPN
17        500          NUM
18       \r\n        SPACE
19     Cabaut        PROPN

Cálculo de etiquetas POS¶

In [17]:
# Calculo de la cantidad de cada tipo de etiqueta POS
pos_counts = df['Etiqueta_POS'].value_counts()
pos_counts
Out[17]:
Etiqueta_POS
NOUN     5131
ADP      4404
PUNCT    4365
DET      3539
VERB     3484
PRON     3232
PROPN    2602
ADV      1824
CCONJ    1719
ADJ      1245
SCONJ    1096
AUX       902
NUM       690
SPACE     365
INTJ       16
PART        5
X           1
Name: count, dtype: int64

Cálculo de sustantivos, adjetivos y verbos más comunes según etiquetado POS¶

In [18]:
# Función que trae palabras más frecuentes con etiqueta POS
def get_top_n_words(df, pos_tag, n=20):
    words = df[df['Etiqueta_POS'] == pos_tag]['Palabra'].value_counts().head(n)
    return words

# Más frecuentes según categoría gramatical
top_nouns = get_top_n_words(df, 'NOUN')
top_adjectives = get_top_n_words(df, 'ADJ')
top_verbs = get_top_n_words(df, 'VERB')

# Impresión palabras más frecuentes
print("Sustantivos más frecuentes:\n", top_nouns)
print("\nAdjetivos más frecuentes:\n", top_adjectives)
print("\nVerbos más frecuentes:\n", top_verbs)
Sustantivos más frecuentes:
 Palabra
capitán    210
tierra     135
gente      124
pueblo     123
agua       102
días       100
millas      96
leguas      95
hombres     90
navíos      82
ciudad      78
camino      70
nación      65
tiempo      64
mujeres     56
día         54
viaje       48
navío       47
cosa        45
]           39
Name: count, dtype: int64

Adjetivos más frecuentes:
 Palabra
llamada       46
general       45
dicho         41
llamado       32
gran          32
grandes       28
grande        27
dichos        24
largos        18
buena         17
buen          17
principal     16
turco         13
junto         13
enteros       13
seguida       12
corriente     11
juntos        11
buenos        10
antedichos    10
Name: count, dtype: int64

Verbos más frecuentes:
 Palabra
llegamos     71
tienen       47
hizo         44
comer        42
quedamos     34
hacer        28
marchamos    27
tiene        26
teníamos     24
llama        23
tenía        23
tenían       22
dijo         22
hacen        21
marchar      20
mandó        20
hicimos      18
llegar       18
dieron       18
llegado      16
Name: count, dtype: int64
In [19]:
#Cálculo de nombres y lugares en el texto de Viaje de Ulrich Schmídel al Río de la Plata
import spacy
# Cargar el modelo en español de spaCy
nlp_es = spacy.load("es_core_news_lg")
#función para encontrar nombre de personas y lugares
def find_names_and_places(text, language="es"):
    if language == "es":
        doc = nlp_es(text)
    else:
        raise ValueError("Error de idioma")

    names = []
    places = []
    for ent in doc.ents:
        if ent.label_ == "PER":
            names.append(ent.text)
        elif ent.label_ == "LOC" or ent.label_ == "GPE":
            places.append(ent.text)

    return names, places


text = ulrico_txt

#aplico la funcion al texto
spanish_names, spanish_places = find_names_and_places(text, language="es")

print("Nombres", spanish_names[:25])
print("Lugares:", spanish_places[:25])
Nombres ['Urich Schmidel', 'Alsina', 'Pietro Mandossa', 'Jacoben Welser de Niremburgo', 'Á LAS CANARIAS', 'Pietro Manthossa', 'Jerg Manthossa', 'Pietro Manthossa', 'Jerg Manthossa', 'Heinrich Paimen', 'Heinrich Paimen', 'Jerg Manthossa', 'No', 'Jerg Manthossa', 'SANTIAGO\r\n\r\nDespués de todo esto', 'Jerg Manthossa', 'San Jacob', 'Polman', 'Fué', 'Pietro Manthossa', 'Hanss Ossorio', 'Juan de Osorio', 'Hans', 'Juan) Ossorio', 'Pietro Manthossa']
Lugares: ['Buenos Aires', 'Andorf', 'Amberes', 'Hispania', 'Khalles', 'Cádiz', 'Khalles', 'Cádiz', 'Platta', 'Indiam', 'Indias', 'Españoles', 'Neerlandeses', 'Sajones', 'Sewastian Neithart', 'Dennerieffe', 'Gomera', 'Polmant', 'Palma', 'San Lucar', 'Cesárea Majestad', 'Españoles', 'Arribamos', 'la Palma', 'Palman']

Gráficos¶

In [20]:
# Gráfico de palabas más frecuentes en texto que fue procesado mediante limpieza

import matplotlib.pyplot as plt
from collections import Counter

# Lectura de texto_limpio.txt
with open('texto_limpio.txt', 'r', encoding='utf-8') as file:
    texto_limpio = file.read()

# Tokenización
palabras = texto_limpio.split()

# Cálcilo de la frecuencia de cada palabra
frecuencia_palabras = Counter(palabras)

# Palabras más frecuentes
palabras_mas_frecuentes = frecuencia_palabras.most_common(50)

# Separación de palabras y frecuencias
palabras, frecuencias = zip(*palabras_mas_frecuentes)

sns.set_style("darkgrid")
# Creación de gráfico
plt.figure(figsize=(12, 6))
plt.bar(palabras, frecuencias, color='violet')
plt.xlabel("Palabras")
plt.ylabel("Frecuencia")
plt.title("Palabras más frecuentes en 'Viaje de Ulrich Schmídel al Río de la Plata'")
plt.xticks(rotation=45, ha='right')
plt.tight_layout()
plt.show()
No description has been provided for this image
In [21]:
# Nube de palabras de Viaje de Ulrich Schmídel al Río de la Plata

from wordcloud import WordCloud
import matplotlib.pyplot as plt

# Lee el texto
with open('texto_limpio.txt', 'r', encoding='utf-8') as file:
    texto_limpio = file.read()

# Crea la nube de palabras
wordcloud = WordCloud(width=800, height=400, background_color='white').generate(texto_limpio)

# Muestra la nube de palabras
plt.figure(figsize=(14, 7))
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
plt.show()
No description has been provided for this image
In [22]:
sns.set_style("darkgrid")

# Tamaño de la figura
plt.figure(figsize=(18, 6))
plt.suptitle("Etiquetas POS más frecuentes en 'Viaje de Ulrich Schmídel al Río de la Plata'", fontsize=14)

# Gráfico de Sustantivos
ax1 = plt.subplot(1, 3, 1)
top_nouns.plot(kind='bar', color='skyblue', ax=ax1)
ax1.set_title('Sustantivos', fontsize=12)
ax1.set_ylabel('Frecuencia', fontsize=10)
ax1.tick_params(axis='x', rotation=45)

# Gráfico de Adjetivos
ax2 = plt.subplot(1, 3, 2)
top_adjectives.plot(kind='bar', color='salmon', ax=ax2)
ax2.set_title('Adjetivos', fontsize=12)
ax2.tick_params(axis='x', rotation=45)

# Gráfico de Verbos
ax3 = plt.subplot(1, 3, 3)
top_verbs.plot(kind='bar', color='lightgreen', ax=ax3)
ax3.set_title('Verbos', fontsize=12)
ax3.tick_params(axis='x', rotation=45)

# Ajustar el espaciado
plt.tight_layout(rect=[0, 0, 1, 0.95])
plt.show()
No description has been provided for this image
In [23]:
from collections import Counter
import matplotlib.pyplot as plt

# Cálculo de la frecuencia de nombres y lugares
name_counts = Counter(spanish_names)
place_counts = Counter(spanish_places)

#Listas para graficar
names, name_freqs = zip(*name_counts.most_common(15))
places, place_freqs = zip(*place_counts.most_common(15))

# Tamaño de la figura
plt.figure(figsize=(18, 8))
plt.suptitle("Nombres y lugares más frecuentes en 'Viaje de Ulrich Schmídel al Río de la Plata'", fontsize=16)

# Gráfico de Nombres
ax1 = plt.subplot(1, 2, 1)
ax1.bar(names, name_freqs, color='skyblue', width=0.8)
ax1.set_title('Nombres', fontsize=14)
ax1.set_ylabel('Frecuencia', fontsize=12)
ax1.tick_params(axis='x', rotation=60, labelsize=10)

# Gráfico de Lugares
ax2 = plt.subplot(1, 2, 2)
ax2.bar(places, place_freqs, color='salmon', width=0.8)
ax2.set_title('Lugares más frecuentes', fontsize=14)
ax2.tick_params(axis='x', rotation=60, labelsize=10)

# Ajustar el espaciado
plt.tight_layout(rect=[0, 0, 1, 0.92])
plt.show()
No description has been provided for this image
In [ ]: