Instalación de librerias
import numpy as np
import pandas as pd
import string
import seaborn as sns
import matplotlib.pyplot as plt
import re
import nltk
import plotly.graph_objects as go
Importar data
df = pd.read_csv("limpieza.csv")
df.head(10)
Análisis exploratorio y visualización
Eliminar duplicados
df.describe()
df['Text'] = df['Text'].astype(str)
df = df.drop_duplicates(subset=['Text'], keep='first')
df.describe()
Idiomas
idioma = df['Language'].unique()
print(len(idioma))
# Cuenta los valores únicos en la columna 'Language' y selecciona los primeros 20
top_20_language_counts = df['Language'].value_counts().head(20)
plt.bar(top_20_language_counts.index, top_20_language_counts.values)
plt.title('Conteo de los 20 idiomas más comunes')
plt.xlabel('Idioma')
plt.ylabel('Conteo')
# Muestra el gráfico
plt.show()
Como se observa en el conjunto de datos, la mayoría de los datos están en inglés. Para simplificar el trabajo futuro, se utilizará solo este idioma en el entrenamiento de los datos.
language_percentages = df['Language'].value_counts(normalize=True)
percentage_en = language_percentages['en'] * 100
print(f"El idioma 'en' representa el {percentage_en}% del total de los datos de la columna 'Language'.")
Sentimientos o etiquetas
sns.countplot(x =df['Label'], order=df['Label'].value_counts().index)
Signos de puntuación
signos = list(string.punctuation)
print(signos)
d_s = {}
for i in signos:
cant = len(df[df["Text"].str.contains(i, regex=False)])
print(f'celdas que contienen el signo {i} : {cant}')
d_s.update({i: cant})
nombres = list(d_s.keys())
valores = list(d_s.values())
# Ordena las listas en función de los valores (de mayor a menor)
nombres, valores = zip(*sorted(zip(nombres, valores), key=lambda x: x[1], reverse=True))
plt.bar(nombres, valores)
plt.xlabel('Signos')
plt.ylabel('Cantidad')
plt.title('Frecuencia de Signos')
plt.xticks(rotation=45) # Para rotar las etiquetas en el eje x si es necesario
plt.show()
Limpieza
Se genera una copia para trabajar en la limpieza del texto.
df_copia = df.copy()
Para visualizar el antes y después de los cambios, se crea una columna nueva en la copia del conjunto de datos.
df_copia.insert(loc=df_copia.columns.get_loc('Text') + 1, column='T_clean', value="")
df_copia['T_clean'] = df_copia['Text']
df_copia.head(2)
# Convierte todos los datos en la columna 'Text' en string
df_copia['T_clean'] = df_copia['T_clean'].astype('str')
#convierte todas las letras del texto en minúsculas.
df_copia['T_clean'] = df_copia['T_clean'].str.lower()
# Crea una expresión regular para encontrar el carácter `\n`
regex = re.compile(r'\n')
# Reemplaza el carácter `\n` con un espacio en blanco
df_copia['T_clean'] = df_copia['T_clean'].replace(regex, ' ')
# Quita usuarios
df_copia['T_clean'] = df_copia['T_clean'].str.replace(r'@\w+', ' ', regex=True)
# Saca links
df_copia['T_clean'] = df_copia['T_clean'].str.replace(r'http\S+|www\S+', '', regex=True)
df_copia.head(18)
# Elimina emojis
emoji_pattern = re.compile("["
u"\U0001F600-\U0001F64F" # emoticons
u"\U0001F300-\U0001F5FF" # symbols & pictographs
u"\U0001F680-\U0001F6FF" # transport & map symbols
u"\U0001F1E0-\U0001F1FF" # flags (iOS)
u"\U00002500-\U00002BEF" # chinese char
u"\U00002702-\U000027B0"
u"\U00002702-\U000027B0"
u"\U000024C2-\U0001F251"
u"\U0001f926-\U0001f937"
u"\U00010000-\U0010ffff"
u"\u2640-\u2642"
u"\u2600-\u2B55"
u"\u200d"
u"\u23cf"
u"\u23e9"
u"\u231a"
u"\ufe0f" # dingbats
u"\u3030"
"]+", flags=re.UNICODE)
df_copia['T_clean'] = df_copia['T_clean'].apply(lambda x: emoji_pattern.sub(r'', x))
df_copia.head(18)
# Quita todos los símbolos
signos_str = "[" + "".join(signos) + "]"
df_copia['T_clean'] = df_copia['T_clean'].str.replace(signos_str, '', regex=True)
# Saca dígitos
df_copia['T_clean'] = df_copia['T_clean'].str.replace('\d', '', regex=True )
df_copia.head(10)
# Elimina las comillas simples de la columna 'Text'
df_copia['T_clean'] = df_copia['T_clean'].str.replace("'", "", regex=True)
# Elimina las comillas raras simples de la columna 'Text'
df_copia['T_clean'] = df_copia['T_clean'].str.replace("’", "", regex=True)
df_copia.sample(5)
# Convierte todos los datos en la columna 'Text' en string
df['Text'] = df['Text'].astype('str')
Función de limpieza
def clean_text_data(text):
# Define los signos de puntuación y el patrón de emojis
signos = list(string.punctuation)
emoji_pattern = re.compile("["
u"\U0001F600-\U0001F64F" # emoticons
u"\U0001F300-\U0001F5FF" # symbols & pictographs
u"\U0001F680-\U0001F6FF" # transport & map symbols
u"\U0001F1E0-\U0001F1FF" # flags (iOS)
u"\U00002500-\U00002BEF" # chinese char
u"\U00002702-\U000027B0"
u"\U00002702-\U000027B0"
u"\U000024C2-\U0001F251"
u"\U0001f926-\U0001f937"
u"\U00010000-\U0010ffff"
u"\u2640-\u2642"
u"\u2600-\u2B55"
u"\u200d"
u"\u23cf"
u"\u23e9"
u"\u231a"
u"\ufe0f" # dingbats
u"\u3030"
"]+", flags=re.UNICODE)
signos_str = "[" + "".join(signos) + "]"
# Convierte el texto a minúsculas
text = text.lower()
# Reemplaza el carácter `\n` con un espacio en blanco
text = re.sub(r'\n', ' ', text)
# Quita los usuarios
text = re.sub(r'@\w+', ' ', text)
# Quita los links
text = re.sub(r'http\S+|www\S+', '', text)
# Elimina los emojis
text = emoji_pattern.sub(r'', text)
# Quita todos los símbolos
text = re.sub(signos_str, '', text)
# Quita todos los dígitos
text = re.sub('\d', '', text )
# Elimina las comillas simples y raras simples del texto
text = re.sub(r"'", "", text)
text = re.sub(r"’", "", text)
text = re.sub(r"“", "", text)
text = re.sub(r"”", "", text)
return text
df['Text'] = df['Text'].apply(clean_text_data)
df.sample(10)
text= "“🎉Just finished my latest web design project!💻 Feeling like a #CSS wizard🧙♂️. Please, no requests for website cloning!🚫😅 #WebDesign #CodingLife”"
#text = "so happy for her she’s been incredible"
print(clean_text_data(text))
df = df[df['Language'] == 'en']
df
Visualizaciones post-limpieza
# Creamos una lista para almacenar la longitud de cada tweet
text_len = [len(text.split()) for text in df.Text]
# Creamos un nuevo dataframe con las longitudes
df_lengths = pd.DataFrame(text_len, columns=['Text_len'])
# Contamos la cantidad de tweets por cantidad de palabras
counts = df_lengths['Text_len'].value_counts().sort_index()
# Creamos las etiquetas y los valores para el gráfico
labels = counts.index
values = counts.values
# Creamos el gráfico
layout = go.Layout(title='Distribución de la cantidad de palabras en los tweets')
fig = go.Figure(data=[go.Bar(x=labels, y=values)], layout=layout)
fig.show()
from wordcloud import WordCloud
import matplotlib.pyplot as plt
all_tweets = ' '.join(tweet for tweet in df.Text)
wordcloud = WordCloud(width=800, height=400, random_state=21, max_font_size=110).generate(all_tweets)
plt.figure(figsize=(10, 7))
plt.imshow(wordcloud, interpolation="bilinear")
plt.axis('off')
plt.show()
Verificación previa al entrenamiento
# Crea una lista para almacenar los índices de los datos que no son válidos
invalid_indices = []
for i, text in enumerate(df['Text']):
if not text:
invalid_indices.append(i)
elif not text.split():
invalid_indices.append(i)
# Imprime los índices de los datos inválidos
print(invalid_indices)
# Crea una lista para almacenar los textos que no estén en minúscula
not_lowercase_texts = []
positions = []
for i, text in enumerate(df['Text']):
if not text.islower():
not_lowercase_texts.append(text)
positions.append(df.index[i])
# Imprime la lista de textos que no estén en minúscula
print(not_lowercase_texts)
# Imprime la lista de posiciones
print(positions)
Modelo de clasificación
import nltk
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer
from sklearn.feature_extraction.text import TfidfVectorizer
nltk.download('omw-1.4')
nltk.download('stopwords')
nltk.download('wordnet')
lemmatizer = WordNetLemmatizer()
stop_words = set(stopwords.words('english'))
def preprocess_text(text):
words = text.lower().split() # Convertir a minúsculas y dividir en palabras
words = [word for word in words if word not in stop_words] # Eliminar palabras vacías
words = [lemmatizer.lemmatize(word) for word in words] # Lematizar las palabras
return ' '.join(words)
df['Text'] = df['Text'].apply(preprocess_text)
vectorizer = TfidfVectorizer()
features = vectorizer.fit_transform(df['Text'])
from sklearn.model_selection import train_test_split
# Divide los datos en entrenamiento y prueba
X_train, X_test, y_train, y_test = train_test_split(features, df['Label'], test_size=0.25, random_state=42)
from sklearn.tree import DecisionTreeClassifier
model = DecisionTreeClassifier(random_state=42)
model.fit(X_train, y_train)
from sklearn.metrics import classification_report
# Usa el modelo para hacer predicciones en el conjunto de prueba
y_pred = model.predict(X_test)
# Calcula la precisión del modelo
accuracy = model.score(X_test, y_test)
# Imprime la precisión del modelo
print(f'Accuracy: {accuracy}')
# Genera y muestra el informe de clasificación
report = classification_report(y_test, y_pred)
print(report)
# Preprocesar un tweet
text = "Missed my flight due to a last-minute gate change.😞 Now I have to wait for hours for the next one. Feeling really disappointed.😔 #TravelIssues #Disappointed"
text = clean_text_data(text)
# Transforma el texto en características
features = vectorizer.transform([text])
# Usa el modelo para predecir el sentimiento
sentiment = model.predict(features)
print(f'el sentimiento del tweet es: {sentiment}')