<jupyter_start><jupyter_text>EDAPara describir la data que tenemos empecemos por la cantidad de datos que tenemos y las tesis:  FormatoEl formato de las tesis es archivos pdfs, al principio se determina los registros de las tesis que deben ser descargados, estos archivos fueron obtenidos desde el siguiente link: http://saber.ucv.ve/handle/10872/2/browse?type=dateissued&sort_by=2&order=ASC&rpp=8211&etal=0&submit_browse=ActualizarEn este link fue la manera en que obtenemos todas las tesis, dependiendo de la fecha de consulta puede que alla mas tesis subidas en la pagina. Para obtener este link se navega desde la pagina de inicio luego en 2) Tesis, luego se selecionar pregrado en el menu dropdown y luego en ir; se selecciona pregrado en las letras azules; esto nos devuelve al menu anterior pero con pregrado preseleccionado (el url donde se empieza es importante ya que si se selecciona el siguiente paso de Fecha de publicacion, siempre va a Tesis); Se escoge fecha de publicacion y nos da el siguiente url: http://saber.ucv.ve/handle/10872/2/browse?type=dateissued&submit_browse=Fecha+Publicaci%C3%B3n Si luego le damos al boton de actualizar para mostrar mas resultados nos damos cuenta que el valor `rpp` si es cambiado nos pueden enseñar todas las tesis que necesitamos el resultado es http://saber.ucv.ve/handle/10872/2/browse?type=dateissued&sort_by=2&order=ASC&rpp=30&etal=0&submit_browse=ActualizarDe esta forma se logro obtener el link para descargar todas las tesis en una sola pagina de HTML. Datos a extraerAhora, los datos a extraer de las tesis son: - Año de la tesis (Ejm: 27-May-2011)- Titulo de la tesis (Ejm: Estudio de sobretensiones por maniobra debido a energización de bancos de condensadores y transformadores en líneas de transmisión de 115kV) - Autor de la tesis (Ejm: <NAME>., <NAME>.)- Tamaño del archivo (Ejm: 6.77 MB)- Link de la tesis (Ejm: http://saber.ucv.ve/handle/10872/11222)- Link de direccion de tesis donde esta el pdf (este es el descargable) (Ejm: http://saber.ucv.ve/bitstream/10872/17712/1/TESIS%20DE%20GRADO%20LUIS%20DE%20GREGORIO.pdf)- Resumen (Este dato esta vacio por la cantidad de erroes que se podian presentar, ya sea de caracteres o de falta de resumen) Para extraer todos estos datosAl final estos datos seran almacenados un un csv, que luego puede utilizarce este data frame para realizar la operacion de descarga de el link donde esta el pdf, los demas datos pueden ser utilizados como metada del archivo.El archivo `scraperv3.py` es el encargado de obtener todos los datos de la tesis y guardalos en un archivo csv. El la funcion main se especifica la cantida de archivos a guardar, en este caso se utilizaron **8211**Estos datos se guardaron en `csv_files/url_thesis_8211.csv` Estos fueron todos los datos<jupyter_code>## Muestra de el archivo inicial con scrapers
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

df = pd.read_csv("../csv_files/url_thesis_8211.csv")
df<jupyter_output><empty_output><jupyter_text>Primer data frame: Todas las tesisEste tiene 8211 filas y 8 columnas, de aqui se puede sacar los siguientes datos. Tamaño promedio de las tesis, año con más tesis.El formato de el tamaño de las tesis es string este debe ser convertido a bytes y a flotante<jupyter_code>size_df = df[['index', 'size']]
size_df
def get_bytes(size):
    # Para convertir los datos a bytes y a flotante
    number, unit = size.split()
    if unit == 'MB':
        number = float(number)
    if unit == 'kB':
        number = float(number) / 1000
    return number
df_byte = df.copy()
do_bytes = np.vectorize(get_bytes)
df_byte['size'] = do_bytes(df_byte['size'])
df_byte
df_byte.info()
df_byte.describe()
size_GB = df_byte['size'].sum()/1000
size_GB<jupyter_output><empty_output><jupyter_text>Tamaño de las tesisDe estos valores la media es 5 MB con una desviacion estandar de 14.8 MB donde el valor minimo es 0.00337 MB o lo que es igual a 3.37 kB. El archivo más pesado siendo de 463 MB.El tamaño total de tesis es 44.7 GB.  Fecha más comun de las tesis<jupyter_code>date_df = df_byte.copy()
date_df.head()
date_df['thesis_year_dt'] = pd.to_datetime(date_df['thesis_year'])
date_df.head()
dates = date_df.groupby(date_df['thesis_year_dt'].dt.year)
dates.size()<jupyter_output><empty_output><jupyter_text>DescripcionPara la fecha de extración de 02 de Abril donde se encontraban 8211 tesis de pregrado, se observa la siguiente distribuccion de años:- El año con mas tesis es 2017 con 1817 tesis- El año con menos tesis son 2009 y 2010.  Segundo data frame: Descargado o no?Luego de tener cuales tesis descargar y el link de descarga de los pdfs se procede a descargar todas las tesis. Esta descarga puede dar diferentes tipos de errores, se procede a tener varios reintentos, con 10 segundos de espera con `backoff_factor` de 1 para cada reintento. Se hacen 5 reintentos:```pythonimport requestsfrom requests.adapters import HTTPAdapter, Retrys = requests.Session()Retry(total=5, backoff_factor=1, status_forcelist=[ 502, 503, 504 ])pdf_response = s.get(url, timeout=10.0)```Con 1 segundo de `backoff_factor` se realizan `total=5` reintentos entonces:Se realizan reintentos en segundos:[0.5, 1, 2, 4, 8]El `timeout=10.0` en request es el tiempo que tarda esperando una respuesta antes de seguir.`status_forcelist` Son los codigos de error donde se reintenta otra vez.Luego de descargarlas se realiza una comparacion si el archivo existe, es decir si fue descargado. Esta comparacion se realiza en el archivo `scripts/preprocessing_files/check_existance.py` Este nos da un nuevo data frame.<jupyter_code>## Muestra el archivo con los archivos descargados en una nueva columna
import pandas as pd
import numpy as np

df = pd.read_csv("../csv_files/url_thesis_8211_exist.csv")
df
## Data frame con los que existe
df_exist = df[df['exist'] == True]
df_exist
len(df) - len(df_exist)
(38*100)/8211<jupyter_output><empty_output><jupyter_text>Archivos no descargadosDe todas las tesis inicialmente mapeadas 8211, 38 no fueron descargadas, esto se debe a que hubo varios erroes en la descarga. Dando un total de 8173 Tesis de pregrado que fueron descargadas o completamente o parcialmente. Esto significa 0.462% de perdidas en la descargaEste comentario parcial se debe a que incluso si fueron descargadas y el archivo existe estas tesis pudieron descargarse con errores, volviendolas inaccesibles.Para esto se realiza tener un data frame que no enseñe solo las tesis que son accesibles, incluso si son imagenes.Este proceso se realiza en el notebook `notebooks/delete_not_exist.ipynb` Donde los archivos descargados que tienen errores son eliminados, dando como resultado el segundo dataframe con solo los archivos pdfs que pueden ser realmente leidos. Este archivo es: `data/url_thesis_8211_with_pdf_scan.csv`<jupyter_code>## Muestra el archivo con los archivos descargados en una nueva columna
import pandas as pd
import numpy as np

df = pd.read_csv("data/url_thesis_8211_with_pdf_scan.csv")
df
isPDF_df = df[df['isPDF']==True]
isPDF_df
len(df) - len(isPDF_df)
(290*100)/8173<jupyter_output><empty_output><jupyter_text>Tercer Dataframe: Archivos con erroresDe las 8211 tesis 8173 se lograron descargar y de las 8173 tesis 290 se descargaron con error (lo que quiere decir que 3.54% de las tesis descargadas tienen error), errores que la hacen imposible acceder a ella, ni como imagen ni como texto. Dando como total 7883 tesis de pregrado que si se pueden leer como pdf, es decir, son archivos que si se pueden abrir con un visor o editor de pdfs.  Es imagen o es textoDe estas 7883 tesis que vamos a tomar, tambien en el archivo `notebooks/delete_not_exist.ipynb` Podemos encontrar las 5 condiciones de saber si el archivo es imagen o es pdf. Criterio de clasificaciónPara determinar que una tesis es escaneada y no contiene texto, se revizaron 5 tesis del primer lote inicial y se determino revisando todas las hojas manualmente que la mayoria eran imagenes. Con esto en mente y teniendo en cuenta que se requiere clasificar por carrera y esta informacion se encuentra normalmente en las primeras paginas de las tesis, el criterio para determinar si una tesis mayoritariamente imagenes que requieres OCR (Reconocimineto optico de caracteres) para pasar a texto queda de la siguiente manera:- La primera hoja es imagen o no.- La segunda hoja es imagen o no.- La hoja del medio mas uno es imagen o no.- La hoja del final -20 es imagen o no (esto es por la bibliografia).- Una hoja aleatoria que no sea la primera ni la segunda es imagen o no.Para determinar si es imagen o no se utilizo la funcion de `pdfplumber` `extract_text()` si esta funcion retornaba '' un caracter vacio significaba que la pagina no contiene texto crudo si no en formato de una imagen escaneada.Si el archivo pdf cumple con 3 de las 5 condiciones se considera que es imagen, de lo contrario es texto.Las 5 tesis revisadas en cuestion:1) http://saber.ucv.ve/handle/10872/315   2) http://saber.ucv.ve/handle/10872/336   3) http://saber.ucv.ve/handle/10872/341   4) http://saber.ucv.ve/handle/10872/318   5) http://saber.ucv.ve/handle/10872/314 (El resumen era texto pero el resto era escaneado)  Cuarto data frame: Imagen o texto?Este dataframe contiene informacion de si la tesis es imagen o es texto `data/url_thesis_8211_with_pdf_scan_image.csv`<jupyter_code>## Muestra los archivos que son imagenes en una nueva columna
import pandas as pd
import numpy as np

df = pd.read_csv("data/url_thesis_8211_with_pdf_scan_image.csv")
df
df_scan = df[df['isScan']==False]
df_scan = df_scan.sort_values('isScan', ascending=False)
df_scan
len(df) - len(df_scan)
(82*100)/7883<jupyter_output><empty_output><jupyter_text>Resultados de imagenesSolo 82 tesis eran imagenes, el resto era texto crudo, entonces de 7883 tesis que se descargaron correctamente, 7801 eran texto. Sacando resultados parecidos entones a la hora de tamaños que nos queda. Lo que significa que solo 1.04% de las tesis descargadas que se pueden abrir, son imagenes.<jupyter_code>df_byte_text = df_scan.copy()
df_byte_text['size'] = do_bytes(df_scan['size'])
df_byte_text
df_byte_text.describe()
size_GB = df_byte_text['size'].sum()/1000
size_GB<jupyter_output><empty_output><jupyter_text>Tamaño de las tesis de solo textoDe estos valores la media es 5.2 MB con una desviacion estandar de 14.8 MB donde el valor minimo es 0.00568 MB o lo que es igual a 5.68 kB. El archivo más pesado siendo de 463 MB.El tamaño total de tesis es 41.071 GB.  Quinto data frame: Escuelas Criterio de busqueda de carreraPara determinar la escuela a la que pertenece una tesis, se tiene que pasar el texto de las paginas pdf a texto crudo, este texto tiene que pasar por un proceso de limpiado para eliminar multiples espacios en blanco, acentos y saltos de linea. Estos luego son comparados por las carreras en `escuelas.json`.```json"facultad": "Facultad de Ingeniería",    "escuela": [        "Escuela de Ingeniería Civil",        "Escuela de Ingeniería Eléctrica",        "Escuela de Geología, Minas y Geofísica",        "Escuela de Ingeniería Química",        "Escuela de Ingeniería de Petroleo",        "Escuela de Ingeniería Mecanica",        "Escuela de Ingeniería Metalúrgica y Ciencia de los Materiales"    ]    },    {        "facultad": "Facultad de Agronomía",        "escuela": [            "Escuela de Agronomía"        ]    },    {        "facultad": "Facultad de Arquitectura y Urbanismo",        "escuela": [            "Escuela de Arquitectura"        ]    },    {        "facultad": "Facultad de Ciencias",        "escuela": [            "Escuela de Biología",            "Escuela de Computación",            "Escuela de Física",            "Escuela de Geoquímica",            "Escuela de Matemática",            "Escuela de Química"        ]    },    {        "facultad": "Facultad de Ciencias Económicas y Sociales",        "escuela":[            "Escuela de Administración y Contaduría",            "Escuela de Antropología",            "Escuela de Estadística y Ciencias Actuariales",            "Escuela de Economía",            "Escuela de Estudios Internacionales",            "Escuela de Sociología",            "Escuela de Trabajo Social"        ]     },```No es sensible a mayusculas.La oracion de especificacion de la escuela tiene que ser exacta, esta se puede ser encontrar en el encabezado o por la firma del acta.Por lo tanto se especifica en que paginas se buscara la escuela en las primeras 10 paginas si ocurre 1 match entonces se declarara esa como la escuela.Se utilizo apache tika para obtener el texto de las carreras, el hecho de utilizar apache tika en vez de pdfplumber, es que apache tika es considerablemente mejor al tratar con acentos y pdfs, es en general mas preciso obteniendo las carreras.Solo se comprobo en las primeras 6000 palabras y las ultimas 6000 paginas si habia un encuentro con una carrera. Esto ayudo a que el procesado de cada archivo fuera mas rapido, debido a que si se trata de procesar toda la tesis en apache tika esto daba errores.La memoria y procesamiento del matcher tuvo que hacerse por batches de 20 con cada uno teniendo al alrededor de 391 tesis. Despues cada uno de los vectores resultados se unieron para dar el dataframe final con todas las tesis.No se tiene una metrica exacta de cual fue la precision de carreras clasificadas apropiadamente, pero realizando revisiones rapidas se nota que la mayoria fue clasificada correctamente. De **7801** se paso a **7149** Esta es la cantidad de tesis con escuela encontrable, es decir que no dio no School o None.<jupyter_code>import json
  
# Opening JSON file
f = open('data/escuelas.json')
  
# returns JSON object as 
# a dictionary
escuelas = json.load(f)

escuelas
counter = 0
for i in escuelas:
    counter += 1
    
counter
# Cantida de facultades
counter = 0
for i in escuelas:
    for esc in i['escuela']:
        counter += 1
        
counter
#Cantidad de escuelas
## Muestra los archivos que son imagenes en una nueva columna
import pandas as pd
import numpy as np

df = pd.read_csv("data/url_thesis_8211_with_pdf_scan_image.csv")
df_scan = df[df['isScan']==False]
df_scan = df_scan.sort_values('isScan', ascending=False)
df_scan
# Se tiene que dividir en 2 partes por limitaciones de la memoria
df_splited_scan = np.array_split(df_scan, 20)
#Esta es la cantidad de filas que tiene cada particion 391 a 390
len(df_splited_scan[0])
#Esta son todas las particiones con las escuelas clasificadas ahora toca unirlas
import pandas as pd
import numpy as np
import os

## get dataframe with text only thesis
csv_source0 = "./data/splitted/thesis_df_splited0_with_school.csv"
csv_source1 = "./data/splitted/thesis_df_splited1_with_school.csv"
csv_source2 = "./data/splitted/thesis_df_splited2_with_school.csv"
csv_source3 = "./data/splitted/thesis_df_splited3_with_school.csv"
csv_source4 = "./data/splitted/thesis_df_splited4_with_school.csv"
csv_source5 = "./data/splitted/thesis_df_splited5_with_school.csv"
csv_source6 = "./data/splitted/thesis_df_splited6_with_school.csv"
csv_source7 = "./data/splitted/thesis_df_splited7_with_school.csv"
csv_source8 = "./data/splitted/thesis_df_splited8_with_school.csv"
csv_source9 = "./data/splitted/thesis_df_splited9_with_school.csv"
csv_source10 = "./data/splitted/thesis_df_splited10_with_school.csv"
csv_source11 = "./data/splitted/thesis_df_splited11_with_school.csv"
csv_source12 = "./data/splitted/thesis_df_splited12_with_school.csv"
csv_source13 = "./data/splitted/thesis_df_splited13_with_school.csv"
csv_source14 = "./data/splitted/thesis_df_splited14_with_school.csv"
csv_source15 = "./data/splitted/thesis_df_splited15_with_school.csv"
csv_source16 = "./data/splitted/thesis_df_splited16_with_school.csv"
csv_source17 = "./data/splitted/thesis_df_splited17_with_school.csv"
csv_source18 = "./data/splitted/thesis_df_splited18_with_school.csv"
csv_source19 = "./data/splitted/thesis_df_splited19_with_school.csv"

# Unir las tesis
csv_a = []
csv_a.append(pd.read_csv(csv_source0))
csv_a.append(pd.read_csv(csv_source1))
csv_a.append(pd.read_csv(csv_source2))
csv_a.append(pd.read_csv(csv_source3))
csv_a.append(pd.read_csv(csv_source4))
csv_a.append(pd.read_csv(csv_source5))
csv_a.append(pd.read_csv(csv_source6))
csv_a.append(pd.read_csv(csv_source7))
csv_a.append(pd.read_csv(csv_source8))
csv_a.append(pd.read_csv(csv_source9))
csv_a.append(pd.read_csv(csv_source10))
csv_a.append(pd.read_csv(csv_source11))
csv_a.append(pd.read_csv(csv_source12))
csv_a.append(pd.read_csv(csv_source13))
csv_a.append(pd.read_csv(csv_source14))
csv_a.append(pd.read_csv(csv_source15))
csv_a.append(pd.read_csv(csv_source16))
csv_a.append(pd.read_csv(csv_source17))
csv_a.append(pd.read_csv(csv_source18))
csv_a.append(pd.read_csv(csv_source19))
concat_df = pd.concat(csv_a,axis=0)
concat_df
concat_df_gb = concat_df.groupby('school_simple')
concat_df_gb.size()
# Lista de tesis que dieron None
gb = concat_df_gb.groups
key_list_from_gb = ['None']
for key, item in concat_df_gb:
    if key in key_list_from_gb: 
        print(concat_df_gb.get_group(key), "\n\n")
# Tesis que dieron No School
gb = concat_df_gb.groups
key_list_from_gb = ['No School']
for key, item in concat_df_gb:
    if key in key_list_from_gb: 
        print(concat_df_gb.get_group(key), "\n\n")<jupyter_output>index  thesis_year                                       thesis_title  \
15    5556  29-Mar-2017  Aplicabilidad de áridos reciclados para fabric...   
16    5555  29-Mar-2017  Hidroformilación de 1-octeno catalizada por el...   
23    5546  29-Mar-2017  Desarrollo de una aplicación web móvil multipl...   
59    5540  29-Mar-2017  Determinación de los requerimientos de equipos...   
75    5494  28-Mar-2017  Propuesta de plan de explotación quinquenal 20...   
..     ...          ...                                                ...   
205   2862   1-Dec-2014  Yo, nosotros y ellos 2.0: comparación entre la...   
226   2780  10-Nov-2014  Sistema de Información para la Planificación d...   
228   2778  10-Nov-2014  Mejoras al Prototipo de Sistema de Información...   
315   2996   2-Mar-2015  Descripción ultraestructural y molecular del p...   
385   2925  16-Dec-2014  Identificación y clonación del gen que codific...   

                           thesis_author       size  \
15      [...]<jupyter_text>Cantida de escuelas con documentosEn la UCV hay un total de 43 Escuelas en 11 facultades. El gruppo None se refiere a que hubo un error al buscar la escuela en el archivo, esto puede darse porque el archivo contiene menos de 6000 palabras, esto puede haber pasado porque de los archivos clasificados como texto estos pasaron por error. Ejemplos se pueden ver en los archivos [5257, 4515, 4334]Luego las tesis clasificadas en `No school` son las tesis donde en las primeras y ultimas 6000 no habia una compracion 1 a 1 de las escuelas.Esto nos deja con un total de 636 escuela `No school` y 16 `None` Lo cual son 652 tesis o archivos, que no tienen escuela. Esto nos da un total de 7149 tesis que si tiene escuelas que si tienen.Lo cual se refiere que de 7801 tesis de texto solo 7149 tiene escuela es decir se tiene una perdida de 8.35%. Datos interesantesLa mayor cantida de tesis son de la escuela de enfermeria con 699, seguido de la escuela de quimica con 622, la escuela de computacion con 524.<jupyter_code>## get dataframe with only schools tag thesis
csv_source = "./data/thesis_7801_with_school.csv"
df_schools = pd.read_csv(csv_source)
df_schools = df_schools[df_schools['isScan']==False]
df_schools = df_schools.sort_values('isScan', ascending=False)
len(concat_df) - len(df_schools)
(652*100)/7801
df_schools
## Escuelas complex
df_schools_complex = pd.read_csv('./data/thesis_7149_with_resumen_school_complex.csv')
df_schools_complex
df_gb_school_complex = df_schools_complex.groupby(df_schools_complex['school_complex'])
df_gb_school_complex.size()
#Cantidad de tesis por escuela
df_gb_school_complex.ngroups 
#Cantida de escuelas
import json
file = open('data/escuelas.json', "r")
file = json.load(file)
file
#rows list initialization
rows = []
rows_school = []
  
# appending rows
for data in file:
    data_row = data['facultad']
    for row in data['escuela']:
        rows.append(data_row)
        rows_school.append(row)
        #rows.append(row)
        
#print(rows)
        
df_school = pd.DataFrame(columns = ['facultad', 'school_complex'])
df_school['facultad'] = rows
df_school['school_complex'] = rows_school
df_school
merged_inner = pd.merge(left=df_schools_complex, right=df_school, left_on='school_complex', right_on='school_complex')
merged_inner
merged_gb_complex_school = merged_inner.groupby(merged_inner['facultad'])
merged_gb_complex_school.size()
#Cantidad de escuelas por facultad
c = ['#1b9e77', '#a9f971', '#fdaa48','#6890F0','#A890F0']
merged_gb_complex_school.size().plot(kind = "bar", color=c)
df = merged_inner
temp_df = round((df.groupby('facultad').size().sort_values(ascending=False) / df.groupby('facultad').size().sort_values(ascending=False).sum())*100, 2)
    
ax = temp_df.plot(kind='bar', color=c)
    
ax.bar_label(ax.containers[0])
        
plt.show()

# Enseñar porcetaje de todas las facultades.
merged_gb_complex_school_facultad = merged_inner.groupby(['facultad', 'school_complex'])
merged_size_f_scool = merged_gb_complex_school_facultad.size()
merged_size_f_scool
only_ciencias = merged_inner[merged_inner['facultad']=='Facultad de Ciencias']
only_ciencias_gb = only_ciencias.groupby(['school_complex'])
only_ciencias_gb.size()
c = ['#1b9e77', '#a9f971', '#fdaa48','#6890F0','#A890F0']
only_ciencias_gb.size().plot(kind = "bar", color=c)
df = only_ciencias
temp_df = round((df.groupby('school_complex').size().sort_values(ascending=False) / df.groupby('school_complex').size().sort_values(ascending=False).sum())*100, 2)
    
ax = temp_df.plot(kind='bar')
    
ax.bar_label(ax.containers[0])
        
plt.show()

# Enseñar porcetaje de todas las facultades.
only_ing = merged_inner[merged_inner['facultad']=='Facultad de Ingeniería']
only_ing_gb = only_ing_gb.groupby(['school_complex'])
only_ing_gb.size()
c = ['#1b9e77', '#a9f971', '#fdaa48','#6890F0','#A890F0']
only_ing_gb.size().plot(kind = "bar", color=c)
df = only_ing
temp_df = round((df.groupby('school_complex').size().sort_values(ascending=False) / df.groupby('school_complex').size().sort_values(ascending=False).sum())*100, 2)
    
ax = temp_df.plot(kind='bar')
    
ax.bar_label(ax.containers[0])
        
plt.show()

# Enseñar porcetaje de todas las facultades.<jupyter_output>/home/heider/Codes/thesis_v4/env/lib/python3.8/site-packages/IPython/core/pylabtools.py:151: UserWarning: Tight layout not applied. The bottom and top margins cannot be made large enough to accommodate all axes decorations.
  fig.canvas.print_figure(bytes_io, **kw)<jupyter_text>Facultad con mas tesisLa faculta de ingenieria es la que mas tesis posee de las tesis obtenidas en pregrado, seguidas por la facultad de ciencias.Otro dato es que de las 8211 tesis de pregrado solo 7149 son usables realmente, con texto y con escuela. Esto significa que 1062 tesis se perdieron. Lo cual significa una perdida de 12.933% desde la data inicial.De las 11 facultades solo estan reflejadas 7. De las 43 Escuelas solo estan reflejadas 34 escuelas en las tesis descargadas.<jupyter_code>8211 - 7149
(1062*100)/8211<jupyter_output><empty_output><jupyter_text>Conclusiones- Primer dataframe (Todas las tesis): Con un total de 8211.- Segundo dataframe (Descargado o no?): De todas las tesis inicialmente mapeadas 8211, 38 no fueron descargadas, esto se debe a que hubo varios erroes en la descarga. Dando un total de 8173 Tesis de pregrado que fueron descargadas o completamente o parcialmente. Esto significa 0.462% de perdidas en la descarga.- Tercer dataframe (Accesible o no?) De las 8211 tesis 8173 se lograron descargar y de las 8173 tesis 290 se descargaron con error (lo que quiere decir que 3.54% de las tesis descargadas tienen error), errores que la hacen imposible acceder a ella, ni como imagen ni como texto. Dando como total 7883 tesis de pregrado que si se pueden leer como pdf, es decir, son archivos que si se pueden abrir con un visor o editor de pdfs.- Cuarto dataframe (Imagen o texto?): Solo 82 tesis eran imagenes, el resto era texto crudo, entonces de 7883 tesis que se descargaron correctamente, 7801 eran texto. Sacando resultados parecidos entones a la hora de tamaños que nos queda.  Lo que significa que solo 1.04% de las tesis descargadas que se pueden abrir, son imagenes.- Quinto dataframe (Escuelas): Esto nos deja con un total de 636 escuela `No school` y 16 `None` Lo cual son 652 tesis o archivos, que no tienen escuela. Esto nos da un total 7149 tesis, antes de 7801 que si tiene escuelas que si tienen. Lo cual se refiere que de 7801 tesis de texto solo 7149 tiene escuela es decir se tiene una perdida de 8.35%. Otros datos:- De las 11 facultades solo estan reflejadas 7. De las 43 Escuelas solo estan reflejadas 34 escuelas en las tesis descargadas.- La escuela mas comun es la `Escuela de Enfermería` con 699 que representa 9.77% de todas las ecuelas.- La facultad mas comun es la `Facultad de Ingeneria` con 2388 tesis lo cual representa 33.403% de todas las tesis.- La facultad de ciencias representa 25.82% con 1846 ejemplares.- La escuela de quimica tiene 622 tesis en la facultad de ciencias la cual la hace la mayor escuela en ciencias en terminos de tesis. La cual representa 33.69% de las tesis (1846)- La escuela de computacion con 524 ejemplares representa 28.38% de las tesis de la facultad de ciencias y 7.32% de las tesis de toda la universidad.<jupyter_code>#Escuela de enfermeria porcentaje
699*100/7149
# Facultad de Ingeneria porcentaje
2388*100/7149
#Facultad de ciencias porcentaje
1846*100/7149
# Representacion mas amplia en ciencia (quimica)
622*100/1846
#Escuela de computacion
524*100/1846
#Escuela de computacion en porcentaje con la universidad
524*100/7149<jupyter_output><empty_output><jupyter_text>Graficos<jupyter_code>import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

tesis_number = [8211, 8173, 7883, 7801, 7149]
tesis_legend = ['Total Tesis', 'Tesis Descargadas', 'Tesis sin Error', 'Tesis Texto', 'Tesis con Escuela']
tesis_diff = [0, 38, 290, 82, 652]
d = {'tesis_number':tesis_number,'tesis_legend':tesis_legend}

data_frame = pd.DataFrame(d)

data_frame.plot(kind='line', color='blue', x='tesis_legend')
data_frame['tesis_number'].plot(marker='*', linestyle = 'None', color='black', ms=10)

## Grafico de como las cantidad de tesis fue degradando con el tiempo.
### Valores de los modelos
model_name = ['BM25_top5', 'Old_NT_top5', 'New_NT_top5', 'model_1_top5', 'model_2_top5', 'model_3_top5',
              'model_4_top5', 'model_5_top5', 'model_6_top5', 'model_7_top5', 'model_8_top5', 'model_9_top5',
              'model_10_top5','BM25_top10', 'Old_NT_top10', 'New_NT_top10', 'model_1_top10', 'model_2_top10',
              'model_3_top10', 'model_4_top10','model_5_top10', 'model_6_top10', 'model_7_top10', 'model_8_top10',
              'model_9_top10', 'model_10_top10']

test_value_recall = [0.56, 0.28, 0.68, 0.64, 0.68, 0.6, 0.52, 0.68, 0.48, 0.68, 0.6, 0.68, 0.68,
                    0.6, 0.4, 0.84, 0.68, 0.8, 0.72, 0.6, 0.84, 0.64, 0.84, 0.8, 0.84, 0.84]
test_value_map = [0.479, 0.19, 0.5076, 0.456, 0.4993, 0.456, 0.363, 0.5076, 0.383, 0.5076, 0.4866, 0.5076, 0.5076,
                 0.471, 0.204, 0.516, 0.4253, 0.502, 0.475, 0.373, 0.516, 0.408, 0.5137, 0.498, 0.516, 0.516]

dev_value_recall = [0.7083, 0.333, 0.7083, 0.75, 0.75, 0.625, 0.5416, 0.75, 0.5416, 0.75, 0.625, 0.75, 0.75,
                   0.75, 0.458, 0.833, 0.7916, 0.7916, 0.75, 0.7083, 0.833, 0.666, 0.833, 0.7916, 0.833, 0.833]
dev_value_map = [0.5305, 0.2131, 0.525, 0.525, 0.499, 0.3541, 0.256, 0.5256, 0.2965, 0.5027, 0.3694, 0.525, 0.525,
                0.535, 0.233, 0.538, 0.404, 0.506, 0.373, 0.278, 0.538, 0.3163, 0.514, 0.395, 0.538, 0.538]

len(model_name)
len(test_value_recall)
len(test_value_map)
len(dev_value_recall)
len(dev_value_map)
aux_df = {'model_name': model_name, 'test_value_recall': test_value_recall, 'test_value_map': test_value_map, 
          'dev_value_recall': dev_value_recall, 'dev_value_map': dev_value_map}

val_df = pd.DataFrame(aux_df)
val_df
val_df['F1_test'] = round((2 * val_df['test_value_map'] * val_df['test_value_recall']) / (val_df['test_value_map'] + val_df['test_value_recall']), 2)
val_df['F1_dev'] = round((2 * val_df['dev_value_map'] * val_df['dev_value_recall']) / (val_df['dev_value_map'] + val_df['dev_value_recall']), 2)
val_df<jupyter_output><empty_output><jupyter_text>TOP 5Se realiza una comparacion entre los documentos recuperados en los top 5, se debe saber que las tesis que tienen<jupyter_code>bm25_fourbest_map_top5 = val_df.loc[val_df['model_name'].isin(['BM25_top5', 'model_9_top5', 'model_10_top5', 'New_NT_top5'])]
bm25_fourbest_map_top5
#comparacion de los 4 mejores modelos con el estadistico
graph_4best = bm25_fourbest_map_top5.set_index('model_name')
ax = graph_4best.plot(kind='barh',figsize=(20, 10))
for container in ax.containers:
    ax.bar_label(container)
bm25_fourworst_map_top5 = val_df.loc[val_df['model_name'].isin(['BM25_top5', 'model_4_top5', 'model_6_top5', 'New_NT_top5'])]
bm25_fourworst_map_top5
graph_4worst = bm25_fourworst_map_top5.set_index('model_name')
ax = graph_4worst.plot(kind='barh',figsize=(20, 10))
for container in ax.containers:
    ax.bar_label(container)
# Modelo viejo y modelo nuevo y estadistico
old_bm25_top5 = val_df.loc[val_df['model_name'].isin(['BM25_top5', 'Old_NT_top5', 'model_10_top5', 'New_NT_top5'])]
old_bm25_top5
graph_old_bm25_top5 = old_bm25_top5.set_index('model_name')
ax = graph_old_bm25_top5.plot(kind='barh',figsize=(20, 10))
for container in ax.containers:
    ax.bar_label(container)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08961440279457208, 'fraction_numerical': 0.053137175869944916, 'mean_word_length': 4.664573820395738, 'pattern_counts': {'":': 10, '<': 53, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '13', 'dir': 'jupyter-structured-clean-dedup', 'id': '652985', 'license': 'Apache-2.0', 'n_tokens_mistral': 11578, 'n_tokens_neox': 10634, 'n_words': 3374, 'path': 'notebooks/EDA.ipynb', 'repo_name': 'HighDeFing/thesis_v4', 'size': '29779'}