File size: 3,760 Bytes
c188624
 
42f33af
75b6dbb
c188624
 
 
 
 
 
 
 
e6aef84
c188624
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5965716
ef692c7
2698828
c188624
75b6dbb
c188624
 
 
 
 
 
 
 
75b6dbb
c188624
 
 
 
8ba2ec3
e29f75c
7ea632a
c188624
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import pandas as pd
import numpy as np
from preprocesamiento_articulos import remove_URL, remove_html_markup, eliminar_puntuacion, eliminar_stopwords, obtener_raices
import streamlit as st


# La idea aqui es colocar el query en minusculas y limpiar el query de palabras vacias y algunos caracteres

def query_processing (query):
    query=eliminar_puntuacion(query) # Quitando signos de puntuacion
    query = query.strip().lower() # Minusculas
    query = eliminar_stopwords(query)
    query = obtener_raices(query)
    return query


# vocab_index = Matriz de terminos del documento, con todas las frecuencias calculadas. En nuestro caso
                # es lo que tenemos en el csv. Se debe cargar a un dataframe.
# Query       = Consulta realizada

def query_score(vocab_index, query):
    for word in np.unique(query.split()):
        freq=query.count(word)
        if word in vocab_index.index:
            tf_idf = np.log2(1+freq) * np.log2(vocab_index.loc[word].inverse_document_frequency)
            vocab_index.loc[word,"query_tf_idf"] = tf_idf
            vocab_index['query_tf_idf'].fillna(0, inplace=True)
                
    return vocab_index # Matriz tf_idf para los terminos de los documentos y para el los terminos del query. Es un DF.
            

 # vocab_index = DataFrame que contiene los scores tf-idf por termino para cada documento y para cada query
# document_index = Lista de los IDs de los documentos
# query_scores = Nombre de la columna del dataframe que contiene los scores tf_idf del query
        

def cosine_similarity(vocab_index, document_index, query_scores):
   
    cosine_scores = {}
    
    query_scalar = np.sqrt(sum(vocab_index[query_scores] ** 2))
    
    for doc in document_index:
            
        doc_scalar = np.sqrt(sum(vocab_index[str(doc)] ** 2))
        dot_prod = sum(vocab_index[str(doc)] * vocab_index[query_scores])
        cosine = (dot_prod / (query_scalar * doc_scalar))
        
        cosine_scores[doc] = cosine
        
    return pd.Series(cosine_scores) # Es una serie pandas que devuelve las puntuaciones de similitud del query para cada
                                    # documento


# data: Dataframe que contiene los ids y el texto de los documentos
# cosine_scores: Serie que contiene los scores de coseno de los documentos
# document_index: Nombre de la columna que contiene los ids de los documentos en el dataframe data

def retrieve_index(data,cosine_scores, document_index, topn=10):
    
    data = data.set_index(document_index)
    data['scores'] = cosine_scores
    df_top_scores=data.reset_index().sort_values('scores',ascending=False).head(topn)
    cutoff=np.average(df_top_scores['scores'])+0.75*np.std(df_top_scores['scores']) # Se usa una formula sugerida en la literatura como score de corte
    df_top_scores=df_top_scores[df_top_scores['scores'] > cutoff]
    
    return df_top_scores.index # Dataframe original con los scores 
                               # del coseno en una columna nueva 


def resultados_consulta(df,articulos_indexados, query):
    indices = pd.Index([], dtype='int64')
    query=query_processing(query)
    qs=query_score(articulos_indexados,query)
    if 'query_tf_idf' in qs.columns:
        cosenos = cosine_similarity(qs, df['ID'].values, 'query_tf_idf')
        indices = retrieve_index(df, cosenos, 'ID', len(df))
    return indices
    
def detalles_resultados(df,indices):   
    top=df.loc[indices]
    top['resumen']=top['resumen'].apply(lambda x: remove_html_markup(x))
    top['resumen']=top['resumen'].apply(lambda x: remove_URL(x))
    top['resumen']=top['resumen'].apply(lambda x: x[0:600] + '[...]' if len(x)>600  else x)
    top=top.loc[:,['titulo', 'link', 'fecha', 'resumen', 'seccion', 'feed']]
    return top