## Identificación de retinopatías El Propósito del siguiente trabajo es identificar los pacientes que tienen complicaciones diabéticas, como lo son la neuropatía, nefropatía y retinopatía de notas médicas. Es el trabajo final del curso Clinical Natural Language Processing impartido en Coursera. Las notas medicas se encuentran en el siguiente linklink para su entrenamiento del modelo: https://raw.githubusercontent.com/hhsieh2416/Identify_Diabetic_Complications/main/data/diabetes_notes.csv Y los datos para su validación se encuentran en el siguiente link: https://raw.githubusercontent.com/hhsieh2416/Identify_Diabetic_Complications/main/data/glodstandrad.csv En primera instancia, se crea el siguiente código para ignorar los warnings: ```python import warnings warnings.filterwarnings("ignore", 'This pattern has match groups') datos = "https://raw.githubusercontent.com/hhsieh2416/Identify_Diabetic_Complications/main/data/diabetes_notes.csv" df = pd.read_csv(datos) # Importando las paqueterías necesarias: import pandas as pd import matplotlib.pyplot as plt import re import numpy as np from sklearn.metrics import confusion_matrix, classification_report # Lectura de datos datos = "https://raw.githubusercontent.com/hhsieh2416/Identify_Diabetic_Complications/main/data/diabetes_notes.csv" df = pd.read_csv(datos) # Análisis grafico de los datos fig, ax = plt.subplots() ax.bar(df['NOTE_ID'],df['TEXT'].str.split().apply(len)) # Cantidad de palabras por reporte de cada paciente identificado por un id conteo = df['TEXT'].str.split().apply(len).tolist() print('Media de palabras: ' + str(np.mean(conteo))) print('Mediana de palabras: ' + str(np.median(conteo))) print('Minimo de palabras: ' + str(np.min(conteo))) print('Maximo de palabras: ' + str(np.max(conteo))) def reporte_paciente(id): resumen = re.findall(r"\w+", str(df[df.NOTE_ID == id]['TEXT'].tolist() )) return resumen # print(reporte_paciente(1)) ``` Ahora bien, se genera una función la cual recibe nuestro DataFrame con las notas médicas, la palabra a buscar y el tamaño de la ventana ## Función sin expresiones regulares ```python def extract_text_window(df, word, window_size, column_name = "TEXT"): #Constants user_input = f'({word})' regex = re.compile(user_input) negative = f'(no history of {word}|No history of {word}|any comorbid complications|family history|father also has {word}|denies {word}|Negative for {word})' regex_negative = re.compile(negative) half_window_size = window_size final_df = pd.DataFrame([]) column_position = df.columns.get_loc(column_name) + 1 #We add 1 cause position 0 is the index #Loop for each row of the column for row in df.itertuples(): #Loop for multiple matches in the same row for match in regex.finditer(row[column_position]): window_start = int([match.start()-half_window_size if match.start()>=half_window_size else 0][0]) window_end = int([match.end() + half_window_size if match.end()+half_window_size <= len(row[column_position]) else len(row[column_position])][0]) final_df = final_df.append({ "WORD": match.group(), "START_INDEX": match.start(), "WINDOW_START": window_start, "WINDOW_END": window_end, "CONTEXT": row[column_position][window_start:window_end], "FULL_TEXT": row[column_position], "NOTE_ID": row[1]}, ignore_index=True) #Extracción de negativos for match in regex_negative.finditer(row[column_position]): final_df2 = final_df[final_df["CONTEXT"].str.contains(pat = regex_negative, regex = True)==False] return "No matches for the pattern" if len(final_df) == 0 else final_df2 # Buscando diabet en las notas médicas df = pd.read_csv("https://raw.githubusercontent.com/hhsieh2416/Identify_Diabetic_Complications/main/data/diabetes_notes.csv") word = "diabet" window_size = 50 #tamaño de la ventana diabetes_notes_window = extract_text_window(df,word,window_size) diabetes_notes_window ``` Se crea una segunda función la cual recibe nuestro DataFrame con nuestras notas médicas, nuestra expresión regular para la palabra a buscar, expresión regular para las expresiones como "historial familiar, no tiene historial de diabetes, no se ha identificado diabetes" entre otras y el tamaño de la ventana al rededor de la palabra a buscar. ## Función con expresiones regulares ```python def extract_text_window_pro(df, pattern,negatives, window_size, column_name = "TEXT"): #Constants half_window_size = window_size final_df = pd.DataFrame([]) column_position = df.columns.get_loc(column_name) + 1 #We add 1 cause position 0 is the index #Loop for each row of the column for row in df.itertuples(): #Loop for multiple matches in the same row for match in re.finditer(pattern,row[column_position]): window_start = int([match.start()-half_window_size if match.start()>=half_window_size else 0][0]) window_end = int([match.end() + half_window_size if match.end()+half_window_size <= len(row[column_position]) else len(row[column_position])][0]) final_df = final_df.append({ "WORD": match.group(), "START_INDEX": match.start(), "WINDOW_START": window_start, "WINDOW_END": window_end, "CONTEXT": row[column_position][window_start:window_end], "FULL_TEXT": row[column_position], "NOTE_ID": row[1]}, ignore_index=True) #Extracción de negativos final_df2 = final_df[final_df["CONTEXT"].str.contains(pat = negatives, regex = True)==False] return "No matches for the pattern" if len(final_df) == 0 else final_df2 # Buscando diabet en las notas médicas df = pd.read_csv("https://raw.githubusercontent.com/hhsieh2416/Identify_Diabetic_Complications/main/data/diabetes_notes.csv") pattern = "diabetes|diabetic" #"(?