From c73633a80901d15d55acb6ed3f915ff22d39dd7a Mon Sep 17 00:00:00 2001 From: Maria Marin Date: Sun, 11 Feb 2024 19:34:05 +0000 Subject: [PATCH] Delete funciones_network_medicine.py --- .../funciones_network_medicine.py | 709 ------------------ 1 file changed, 709 deletions(-) delete mode 100644 Network Medicine/funciones_network_medicine.py diff --git a/Network Medicine/funciones_network_medicine.py b/Network Medicine/funciones_network_medicine.py deleted file mode 100644 index 6e711c0..0000000 --- a/Network Medicine/funciones_network_medicine.py +++ /dev/null @@ -1,709 +0,0 @@ -#! /usr/bin/env python - -""" -# --------------------------------------------------------------------------- -# -# funciones_network_medicine.py -# -# Archivo con todas las funciones que he utilizado para calcular -# los módulos de las enfermedades, su tamaño, y su significancia -# estadísticas. También incluye la función que nos permite representar -# tanto la distribución de degrees del módulo de la enfermedad -# como la distribución de LCCs de redes generadas aleatoriamente (ndp y dp). -# -# TFG: Ciencia de redes y reposicionamiento de fármacos: potencial a través -# de la medicina de redes -# -# María Marín Tercero -# ---------------------------------------------------------------------------- -""" - -import pandas as pd -import numpy as np -import seaborn as sns -import matplotlib.pyplot as plt -import networkx as nx -from tabulate import tabulate -from networkx.algorithms import bipartite -import random -from scipy.stats import norm -from itertools import combinations -import re -from itertools import product - -# ================================================================================= - -def arch_distances(PPI): - - """ - Esta función calcula los SPL desde cada nodo de la red PPI que demos de entrada al resto de nodos de la red. Después,crea un Dataframe que contiene una - columna con todos los nodos, y otra columna con la lista de SPL para cada nodo. Por último, crea un archivo llamado distances.csv con ese DataFrame. - """ - - nodos = [] - d = [] - # Calculo el Shortest Path Length para cada nodo - for source_node in PPI.nodes(): #selecciono un nodo de la red PPI - nodos.append(source_node) #lo añado a la lista de nodos - path_lengths = [] #creo una lista con todos los path lengths para ese nodo - for target_node in PPI.nodes(): #selecciono otro nodo de la red PPI - if source_node != target_node: #me aseguro de que sean nodos diferentes - if nx.has_path(PPI, source_node, target_node): - pl = nx.shortest_path_length(PPI, source=source_node, target=target_node) #calculo el SPL entre ello - path_lengths.append(pl) #añado esa distancia a la lista de todos los path lengths de ese nodo - else: - continue - - d.append(path_lengths) #lista con los SPL de cada nodo - - # Crear DataFrame - data = {'Nodo': nodos, 'Lista Shortest Path Lenght': d} - distances = pd.DataFrame(data) - #Llevo el dataframe a un archivo - distances.to_csv('distances.csv') - -# ================================================================================= - -def degrees_lista(G): - """ - Esta función nos devuelve una lista con los nodos y otra lista con sus degrees - """ - nodos = list(G.nodes()) - degrees = list(dict(G.degree()).values()) - - return nodos, degrees - -# ================================================================================= - -def average_spl(arch): - """ - Esta función calcula el Average SPL para cada nodo a partir de un archivo que contenga todos los SPL entre todos los nodos de la red PPI - """ - ave_spl = [] - average_spl_por_nodo = arch.mean(axis=1) - # Crear un nuevo DataFrame con los resultados - df_average_spl = pd.DataFrame({'Nodo': average_spl_por_nodo.index, 'AverageSPL': average_spl_por_nodo.values}) - return df_average_spl - -# ================================================================================= - -def genes_enf(enf, archivo): - """ - Esta función crea una lista con los genes asociados a la enfermedad "enf" en el archivo dis_gen - - """ - genes=[] - for i, dis in enumerate(archivo["dis"]): #obtengo "posición de la enfermedad en la hoja de datos dis_gen (i) y el id de la enfermedad (dis2)" - if dis == enf: - gen = archivo["gen"][i] #obtengo el valor de la columna "gen" con la misma posición que cada enfermdad - genes.append(gen) #añado los genes a la lista de genes - return genes - -# ================================================================================= - -def pro_gen_dict(lista_genes, archivo): - """ - Esta función crea un diccionario a partir de la lista de genes asociados a la enfermedad con: - key: proteína asociada a cada gen del archivo gen_pro - value: gen relacionado a la proteína key en el archivo gen_pro - """ - dict1={} - for i, gen in enumerate(archivo["gen"]): #bucle que opera sobre gen_pro, que relaciona genes y proteínas. Me guardo la posición del gen (i) y el id del gen (gen) - if gen in lista_genes: #busco cada gen de gen_pro en la lista de genes correspondiente de cada enfermedad - prot = archivo["pro"][i] #si ese gen está en la lista de genes de cada enfermedad, busco la proteína asociada a la misma posición - dict1[prot]= gen #añado al diccionario de cada enfermedad la proteína como key y el gen relacionado como value - return dict1 - -# ================================================================================= - -def gen_pro_PPI(dict1, archivo): - """ - A partir de un diccionario con las relaciones entre las proteínas y genes se asocian con cada una de nuestras enfermedades, - esta función se queda con la relación prot:gen del diccionario solo si dicha prot aparece en la red de PPI del archivo pro_pro - key: proteínas que aparecen en la red PPI - value: genes relacionados con la proteína key - """ - dict2={} - for prot in dict1.keys(): #itero sobre todas las proteínas del diccionario general prot:gen - if prot in archivo["prA"].tolist() or prot in archivo["prB"].tolist(): #selecciono las prots que aparecen en la PPI - dict2[prot] = dict1[prot] #añado al diccionario prot:gen de PPI solo las relaciones prot:gen para prots que estén en la PPI - return dict2 - -# ================================================================================= - -def SG(dic, PPI): - """ - Datos de entrada: diccionario con las proteínas de la PPI (keys) y los genes (values) asociados para una enfermedad, red PPI - Esta función crea una subred solo con las proteínas de la red PPI asociadas a mi enfermedad como nodos - """ - - #Creo una subred solo con las proteínas de la red PPI asociadas a mi enfermedad como nodos - SG = nx.subgraph(PPI, dic.keys()) - return SG - -# ================================================================================= - -def lcc(SG): - """ - Esta función nos da el LCC de las proteínas de la red PPI asociadas a una enfermedad a partir de una subred - formada solo con las proteínas asociadas a la enfermedad - """ - lcc = max(nx.connected_components(SG), key=len) #calculo el lcc (módulo que comprende el mayor número de poteínas de una enfermedad asociadas entre sí) - - #Nuestro objetivo es obtener el número de genes que formen parte del LCC de la enfermedad: - #El número de proteínas de la enfermedad en el LCC es el mismo número que los genes en el LCC - #(porque hemos sacado la lista de proteínas del diccionario en el que forman una tupla con sus genes asociados) - - - return lcc - -# ================================================================================= - -def nodes_by_degree(G): - """ - Esta función nos devuelve un diccionario en el que obtendremos los los degrees como key y, en los values, todos los nodos de la red que contengan ese degree - """ - degree_dict = {} - for node in G.nodes(): - degree = G.degree(node) - - if degree not in degree_dict: - degree_dict[degree] = [] - - degree_dict[degree].append(node) - - return degree_dict - -# ================================================================================= - -def lcc_simulation(G, lcc, PPI, dp=False): - """ - Datos de entrada: subred módulo de la enfermedad (G), PPI y LCC de la enfermedad (lcc). Dp puede ser False para - calcular redes preservar la distribución de degrees del módulo de la enfermedad o True en el caso contrario. - - Esta función devuelve la media y la desviación estándar del LCC de 1000 redes aleatorias con el mismo número - de nodos y links que el gráfico G que demos de entrada. - - Para la creación de estas redes en el caso de dp = False, se distribuyen aleatoriamente las asociaciones entre - proteínas de la enfermedad de forma en la red. Por lo tanto, las redes no tendrán la misma estructuctura que el - módulo de la enfermedad. - - Para la creación de redes en el caso dp = True, se seleccionan nodo en la red PPI con el mismo degree que los - nodos del módulo de la enfermedad. De esta forma, se crran redes con la misma estructura que e módulo de la - enfermedad. - - """ - - #Cálculos previos: - - #Obtengo el total de proteínas de la PPI - nodos_ppi=PPI.nodes() - - #Obtengo el total de las proteínas en el módulo de la enfermedad - nodos_enf = G.nodes() - - #Obtengo el número de proteínas del módulos de la enfermedad - numero_nodos_enf=len(nodos_enf & set(nodos_ppi)) - - #agrupo los nodos según su degree - - grupo_nodos_degree = nodes_by_degree(PPI) - - - #1000 simulaciones aleatorias para calcular 1000 LCC - lista_random= [] - for i in range(1000): - if dp == False: #simulación para non degree preserving - #Obtengo un set aleatorio de proteínas dentro del total de nodos de la red PPI. - #Dicho set presenta un número de nodos que equivale al número de nodos del módulo de la enfermedad - nodos_random = set(random.sample(list(nodos_ppi), numero_nodos_enf)) #mismo número de nodos que el módulo de la enfermedad, tomados de la lista de prots totales de la PPI aleatoriamente - if dp == True: #simulación para degree preserving - nodos_random = set() - for nodo in nodos_enf: #para cada nodo del módulo de la enfermedad - degree = PPI.degree(nodo) #obtengo su degree en la PPI - nodos_disponibles = grupo_nodos_degree[degree] #obtengo un grupo de nodos de la PPI con igual degree al nodo iterado - control = True - while(control): #bucle para elegir los nodos sampleados solo una vez - nodo_elegido = random.choice(nodos_disponibles) #eligo un nodo entre los nodos de la PPI seleccionados en el paso anterior - control = nodo_elegido in nodos_random #compruebo si ese nodo está entre los nodos sampleados - nodos_random.add(nodo_elegido) #añado ese nodo a la lista de nodos que usaré para crear la red aleatoria - #solo se añaden nodos que no estén anteriormente entre los nodos sampleados gracias al bucle while - r = nx.subgraph(PPI,nodos_random) #subred de la PPI con los nodos aleatorios selccionados - r = nx.Graph(r) #para remover los links paralelos - r.remove_edges_from(nx.selfloop_edges(r)) #para eliminar los self-loops que conectan un nodo consigo mismo - lista_random.append(len(max(nx.connected_components(r), key=len))) - media = np.mean(lista_random) #media - std = np.std(lista_random) #desviación estándar - zscore = (len(lcc) - media)/std - - return media, std, zscore, lista_random - -# ================================================================================= - -def rep(nombre_enf, G, PPI, lista_ndp,lista_dp, LCC, media_ndp, std_ndp, zscore_ndp, media_dp, std_dp, zscore_dp): - """ - Datos de entrada: - 1. Nombre de la enfermedad - 2. SG: LCC de las proteínas de la red PPI asociadas a una enfermedad - 3. G: Red PPI - 4. lista_ndp: lista de LCCs (ndp) - 5. lista_dp: lista de LCCs (dp) - 6.LCC: LCC observado de la enfermedad - 7. media_ndp: media de la lista de LCCs (ndp) - 8. std_ndp: desviación estándar de la lista de LCCs (ndp) - 9.zscore_ndp: z-score de la lista de LCCs (ndp) - 10. media_dp: media de la lista de LCCs (dp) - 11. std_dp: desviación estándar de la lista de LCCs (dp) - 12. zscore_dp: z-score de la lista de LCCs (dp) - - Esta función realiza una representación de: - 1. Distribución de degrees - 2. Distribución de LCCs (ndp) - 3. Distribución de LCCs (dp) - """ - #obtengo una lista con los nodos y los degrees de la PPI - G_lista_ppi = degrees_lista(PPI) - - degree_ppi = pd.DataFrame(list(zip(G_lista_ppi[0], G_lista_ppi[1])), columns=['node','degree']) - - #obtengo una lista con los nodos y los degrees de la PPI - G_lista_enf = degrees_lista(G) - - degree_enf = pd.DataFrame(list(zip(G_lista_enf[0], G_lista_enf[1])), columns=['node','degree']) - - - #Agrupo la lista de nodos y degrees de la PPI en función del degree y cuento cuántos nodos de la red tienen ese degree - G_plot_ppi = degree_ppi.groupby('degree').count() - - #Agrupo la lista de nodos y degrees de la enfermedad en función del degree y cuento cuántos nodos de la red tienen ese degree - G_plot_enf = degree_enf.groupby('degree').count() - - #Creo una figura en la que añadiré 3 subplots - fig, axs = plt.subplots(1, 3, figsize=(15, 4)) - - #Representación Distribución de Degrees de la PPI en color azul y degrees de los nodos de la enfermedad en color rojo - axs[0].scatter(G_plot_ppi.index, G_plot_ppi['node'], label='Nodos interactoma', marker='o', color='#79C4FF',s=10) - axs[0].scatter(G_plot_enf.index, G_plot_enf['node'], label='Nodos '+str(nombre_enf) + " module", marker='o', color='#FF7A7A', s=10) - axs[0].set_yscale('log') - axs[0].set_xscale('log') - axs[0].set_xlabel('Grado', fontsize=12) - axs[0].set_ylabel('Nº de nodos', fontsize=12) - axs[0].set_title('Distribución de grados en el interactoma', fontsize=14) - axs[0].legend(loc='upper right') - - #Representación de la distribución de LCC ndp - axs[1].hist(lista_ndp, color = '#79C4FF', bins=20, edgecolor='black') - axs[1].set_xlabel('Nº de nodos en LCC', fontsize=12) - axs[1].set_ylabel('Nº de redes', fontsize=12) - axs[1].set_title('Distribución del LCC en 1000\n redes aleatoria (ndp)', fontsize=14) - axs[1].axvline(x=len(LCC), color='#FF7A7A', linestyle='--') - axs[1].legend(["LCC "+str(nombre_enf)], loc='upper right') - - - #Representación de la distribución de LCC dp - axs[2].hist(lista_dp, color = '#79C4FF', bins=20, edgecolor='black') - axs[2].set_xlabel('Nº de nodos en LCC', fontsize=12) - axs[2].set_ylabel('Nº de redes', fontsize=12) - axs[2].set_title('Distribución del LCC en 1000\n redes aleatoria (dp)', fontsize=14) - axs[2].axvline(x=len(LCC), color='#FF7A7A', linestyle='--') - axs[2].legend(["LCC "+str(nombre_enf)], loc='upper right') - - - # Ajusto el diseño y espacio entre gráficos - plt.tight_layout() - - # Leyenda 1 - texto_leyenda_1 = r'$LCC (ndp)_{\mathrm{obs}}$' + ' (' + r'$\mathrm{mean\ LCC} - \mathrm{STD}$, z-score' + ')' - leyenda_valor_1 = f'{len(LCC)} ({round(media_ndp,2)} - {round(std_ndp,2)}, {round(zscore_ndp,2)})' - fig.text(0.51, -0.05, texto_leyenda_1+str(" = ")+leyenda_valor_1, fontsize=12, ha='center', va='center', bbox=dict(facecolor='white', alpha=0.5, boxstyle='round')) - - #Leyenda 2 - texto_leyenda_2 = r'$LCC (dp)_{\mathrm{obs}}$' + ' (' + r'$\mathrm{mean\ LCC} - \mathrm{STD}$, z-score' + ')' - leyenda_valor_2 = f'{len(LCC)} ({round(media_dp,2)} - {round(std_dp,2)}, {round(zscore_dp,2)})' - fig.text(0.51, -0.15, texto_leyenda_2+str(" = ")+leyenda_valor_2, fontsize=12, ha='center', va='center', bbox=dict(facecolor='white', alpha=0.5, boxstyle='round')) - - # Título general encima de los tres gráficos - plt.suptitle(str(nombre_enf), fontsize=20, y=1.1, fontweight='bold', style='italic') - - # Muestro la figura - plt.show() - -# ================================================================================= - - -def archivo_modulos(nombre_enf, nodes_lcc, arch_datos, SG): - """ - Esta función permite obtener dos archivos: un dataframe con los datos sobre el subgrafo - correspondiente al LCC de una enfermedad, y otro con el Id, el grado en el interactoma, - y el símbolo del gen para cada nodo del subgrafo. - - Datos de entrada: - 1. Nombre_enf: nombre enfermedad - 2. Nodes_lcc: nodos en el componente más conectado del subgrafo de la enfermedad - 3. Archivo_datos: archivo con los datos sobre el grado de cada nodo en el interactoma - 4. SG: subgrafo de la enfermedad - """ - - #obtengo un diccionario con los nodos del módulo de la enfermedad y sus degrees en la PPI - dict_degrees={} #diccionario vacío - for node1 in nodes_lcc: #itero sobre los nodos en el módulo de la enfermedad - for i,node2 in enumerate(arch_datos["Nodo"]): #itero sobre el total de nodos de la PPI - if node1 == node2: #si un nodo de la PPI está en el módulo de la enfermedad - dict_degrees[node1]=arch_datos["Degree"][i] #añado al diccionario el nodo como key y su degree como value - - #Creo una red con las proteínas del LCC de la enfermedad: - mod = SG.subgraph(nodes_lcc) - mod = nx.Graph(mod) #para remover los links paralelos - mod.remove_edges_from(nx.selfloop_edges(mod)) #para eliminar los self-loops que conectan un nodo consigo mismo - - #Convierto el grafo a un DataFrame - mod_df = nx.to_pandas_edgelist(mod) - - #Guardo el df en un archivo - mod_df.to_csv(str(nombre_enf) + " módulo.csv", index = False) - - - #Junto los datos de id, degrees y símbolos (que rellenaré a continuación) - data = {'Id': list(dict_degrees.keys()), 'Degrees': list(dict_degrees.values()), "Symbols":[None] * len(list(dict_degrees.keys()))} - - #Añado los símbolos - for j,prot1 in enumerate(data["Id"]): - for i, prot2 in enumerate(sim["protein_id"]): - if prot1==prot2: - data["Symbols"][j]=sim["gene_symbol"][i] - - # Guarda el DataFrame actualizado en el mismo archivo o en uno nuevo - df = pd.DataFrame(data) - df.to_csv(str(nombre_enf)+' degrees.csv', index=False) - -# ================================================================================= - -def drugs_enf(enf, arch): - """ - Esta función crea una lista con los fármacos asociados a cada enfermedad según el archivo dis_dru_the - """ - drugs=[] - for x, enf2 in enumerate(arch["dis"]): #para la columna "dis" del archivo dis_dru_the, que recoge los id de las enfermedades, me quedo con el id (enf2) y su posición en la columna(x) - if enf == enf2: #si se encuentra una coincidencia entre el id de una de nuestras cuatro enfermedades y el id de una enfermedad en el archivo dis_dru_the - drug = arch["dru"][x] # selecciono la droga asociada al id de esa enfermedad (que se encuentre en su misma fila) - drugs.append(drug) #añado ese fármaco a la lista correspondiente (la que se encuentra en la misma posición en la lista drugs que el id de la enfermedad en la lista enf) - return drugs - - -# ================================================================================= - -def targets(lista_drugs, arch): - """ - Datos de entrada: lista con los fármacos que tratan una enfermedad (lista_drugs) y archivo con las relaciones fármaco-diana (arch) - Esta función nos permite obtener un DataFrame con fármacos en la columna "Fármacos" y sus dianas en la columna "Dianas" - """ - targets_total = [] #lista en la que añadiré los targets de cada fármaco separados por comas - farmacos = [] #lista en la que añadiré los fármacos que estén en el archivo arch - for drug1 in lista_drugs: #itero sobre cada fármaco de la lista de fármacos - targets=[] #lista vacía en la que añadiré los targets de cada fármaco - for i, drug2 in enumerate(arch["dru"]): #itero sobre los fármacos del archivo me quedo con el fármaco (drugs2) y fila (i) en la columna de fármacos del archivo dru_pro - if drug1 == drug2: #si un fármaco de la enfermedad está en el archivo de fármacos-diana - targets.append(arch["pro"][i]) #añado su diana a la lista de targets, que estará en la misma fila (i) en la columna de dianas - - if len(targets) > 0: #comrpuebo que la lista de targets no esté vacía - farmacos.append(drug1) #añado el fármaco a la lista de fármacos para así solamente guardar los fármacos que aparecen en el archivo arch - targets_total.append(targets) #añado la lista de targets de ese fármaco a la lista de targets de todos los fármacos - - data = {"Fármacos": farmacos, "Dianas": targets_total} #junto los datos y los clasifico en Fármacos y Dianas - df = pd.DataFrame(data) #Creo un DataFrame con los resultados - return df - -# ================================================================================= - -def calcular_dc_farmaco(lista_targets, arch_dist, prots_enf, PPI): - """ - Datos de entrada: lista con las dianas de ese fármaco (lista_targets), proteínas del módulo de la enfermedad - (prots_enf), archivo con la matriz de distrancias entre todos los nodos de la PPI (arch_dist), red PPI (PPI) - Función que devuelve el closest measure (dc) de un fármaco y una enfermedad. - """ - targets_en_ppi = set(lista_targets) & set(PPI.nodes()) #lista con las dianas del fármaco que también están en la red PPI - targets_en_enf = set(targets_en_ppi) & set(prots_enf) ##lista con las dianas del fármaco que también forman parte del módulo de la enfermedad - - distancias_enf_target = arch_dist.loc[list(targets_en_ppi), list(prots_enf)].values #genero una matriz con los SPLs entre todas las diana del fármaco y todas las proteínas del módulo de la enfermedad según el archivo de distancias - - filas_no_vacias = ~np.isnan(distancias_enf_target).all(axis=1) #me quedo con las filas que no estén vacías, es decir, elimino las dianas que no tienen ningún camino a ninguna proteína de la enfermedad - - if np.isnan(distancias_enf_target).all(): #si la matriz anterior está vacía - return np.nan #no hay camino entre ninguna diana del fármaco fármaco y la enfermedad - - elif len(targets_en_enf) == len(targets_en_ppi): #si todas las dianas del fármaco forman parte del módulo de la enfermedad - return 0 #el valor dc será 0 - - else: - return np.nanmean(np.nanmin(distancias_enf_target[filas_no_vacias], axis=1)) #en caso contrario, calculo la media entre los SPLs mínimos de las dianas que sí tengan algún camino al módulo de la enfermedad (la media de los valores mínimos de cada fila de mi matriz) - -# ================================================================================= - -def proximity(df, arch_dist, prots_enf, PPI): - """ - Datos de entrada: DataFrame (df) con los "Fármacos" y sus "Dianas; archivo con las - distancias entre todos los nodos de la red (arch_dist); lista de proteínas relacionadas con una enfermedad - (prots_enf); y red PPI (PPI) - Función que nos permite obtener un DataFrame con los valores de proximidad (dc) para una lista de fármacos - y una enfermedad. - """ - dc_farmaco_total = [] #lista en la que guardaré el valor dc de todos los fármacos - enfermedades = [] #lista en la que añadiré si el medicamento pertenece a una enfermedad en concreto - for i, drug in enumerate(df["Fármacos"]): #para cada fármaco del df de fármacos y dianas me quedo con fila (i) - lista_targets = df["Dianas"][i] #obtengo la lista de dianas de ese fármaco, que estará en la misma fila que el fármaco pero en la columna de dianas - dc_farmaco_total.append(calcular_dc_farmaco(lista_targets, arch_dist, prots_enf, PPI)) - - data = {'Fármacos': list(df["Fármacos"]), 'dc': dc_farmaco_total} #guardo la relación entre la lista de fármacos y la de dcs - result_tabla = pd.DataFrame(data) #convierto los reultados en un dataframe - - return result_tabla - -# ================================================================================= - -def proximity_random(df, arch_dist, prots_enf, PPI, num_iteraciones): - """ - Datos de entrada: DataFrame (df) con los "Fármacos" y sus "Dianas", archivo con las - distancias entre todos los nodos de la red (arch_dist), lista de proteínas relacionadas con una enfermedad - (prots_enf), red PPI (PPI) y el número de iteraciones (num_iteraciones) - que serán realizadas para calcular los dc (num_iteraciones) - Función que nos permite obtener un DataFrame con los valores de proximidad (dc) medios calculados a partir de: - - 1000 módulos aleatorios de proteínas con el mismo número de proteínas y la misma distribución de degrees - que el módulo de una enfermedad - - 1000 módulos aleatorios de dianas con el mimso número de proteínas y la misma distribución de degrees que - cada fármaco del DataFrame de fármacos y dianas - """ - grupo_nodos_degree = nodes_by_degree(PPI) #agrupo los nodos según su degree - - # Inicializo una matriz con valores nulos que tenga el mismo número de filas que el total de fármacos de Dataframe - #y el mismo número de columnas que de iteraciones - matriz_proximidad = np.full((len(df["Fármacos"]), num_iteraciones), None, dtype=object) - - for i in range(num_iteraciones): #para cada iteración - - # Módulo enfermedad aleatorio - prots_random = set() #creo un set de proteínas aleatorias - for prot in prots_enf: #para cada proteína del módulo de la enfermedad - degree_prot = PPI.degree(prot) #calculo su degree - prots_disponibles = grupo_nodos_degree[degree_prot] #elijo las proteínas de la PPI con su mismo degree - prots_random.add(np.random.choice(prots_disponibles)) #mismo número de nodos que el módulo de la enfermedad, tomados de la lista de prots totales de la PPI aleatoriamente - - # Módulo diana - targets_random = set() #creo un set de proteínas dianas aleatorias - for j, drug in enumerate(df["Fármacos"]): #para cada fármaco me quedo con su fila (j) - lista_targets = df["Dianas"][j] #me quedo con la lista de dianas de ese fármaco - lista_targets_PPI = set(lista_targets) & set(PPI.nodes()) #me quedo con las dianas del fármaco que estén en la PPI - for target in lista_targets_PPI: #para cada diana de la lista de dianas - degree_target = PPI.degree(target) #calculo su degree - targets_disponibles = grupo_nodos_degree[degree_target] #elijo las proteínas de la PPI con su mismo degree - targets_random.add(np.random.choice(targets_disponibles)) #mismo número de nodos que el módulo de la enfermedad, tomados de la lista de prots totales de la PPI aleatoriament - - #calculo el dc de cada fármaco con el módulo aleatrio de enfermedad y de dianas - dc_farmaco_total = calcular_dc_farmaco(targets_random, arch_dist, prots_random, PPI) - matriz_proximidad[j, i] = dc_farmaco_total #añado el dc de cada fármaco (en la fila j) en la columa de la matriz correspondiente a la iteración (i) - print(i) - - medias_proximidad_farmaco = [] #lista en la que añadiré el promedio de dc tras 1000 iteraciones para cada fármaco - desviacion = [] #lista en la que añadiré la desviación del dc tras 1000 iteraciones para cada fármaco - - for fila in matriz_proximidad: #para cada fila (para cada fármaco) - if all(x is np.nan for x in fila): #si la fila completa es none - medias_proximidad_farmaco.append(np.nan) #añado none a la lista medias_proximidad_farmaco - else: - medias_proximidad_farmaco.append(np.nanmean(fila)) #añado la media de esa fila - desviacion.append(np.nanstd(fila)) #desviación estándar - - data = {'Fármacos': list(df["Fármacos"]), 'dc_mean': medias_proximidad_farmaco, 'dc_std' : desviacion} - result_tabla = pd.DataFrame(data) - - return result_tabla - - -# ================================================================================= - -def determinar_tratamiento(row, arch): - """ - Esta función toma las filas de un archivo tipo DataFrame y añade una columna indicando - si dichos fármacos se emplean para el tratamiento de la demencia, la bipolaridad, - la epilepsia o la esquizofrenia. Finalmente, devuelve el DataFrame original con - la nueva columna Tratamientos añadida. - """ - enfermedad = row['Enfermedades'] #selecciona cada fila de la columna enfermedades - farmaco = row['Fármacos'] #selecciona cada fila de la columna fármacos - codigo_dis = { #código que relaciona nombre y id de la enfermedad - 'Demencia': 'C0497327', - 'Bipolaridad': 'C0005586', - 'Epilepsia': 'C0014544', - 'Esquizofrenia': 'C0036341' - } - - # Añado "yes" a tratamiento si ese fármaco se usa para tratar una de las enfermedades del codigo_dis - codigo_tratamiento = 'yes' if arch[(arch['dis'] == codigo_dis[enfermedad]) & (arch['dru'] == farmaco)].shape[0] > 0 else 'unknown' #si no, añado "unkwown" - - return codigo_tratamiento - -# ================================================================================= - -def combinar_proximidades(enfermedades,farmacos, proximity_files, proximity_random_files, arch): - """ - Esta función crea un DataFrame que contiene los resultados para la proximidad, - la media, la desviación típica y el zscore de la proximidad (obtenidos a partir - de los DataFrames aportados como datos de entrada) para todas las combinaciones - entre la lista de fármacos y la lista de enfermedades proporcionada como datos de entrada. - Columnas DataFrame resultado: - 1. Enfermedades (Demencia, Bipolaridad, Epilepsia o Esquizofrenia) - 2. Fármacos - 3. Tratamiento: columna que indica si el el fármaco de la columna 2 trata a la enfermedad - de la columna 1 ("yes" en caso afirmativo, "unkwown" en el caso contrario - 4. Valor de proximidad a la Enfermedad de la columna 1 - 5. Proximidad aleatoria media a la Enfermedad de la columna 1 - 6. Desviación estándar de en las proximidades aleatorias a la Enfermedad de la columna 1 - 7. Z-Score de la proximidad observada (indicada en la columna 3) en comparación con - la proximidad aleatoria media (en la columna 4) y la desviación estándar de la - proximidad aleatoria (columna 5) - - Datos de entrada: - 1. Lista fármacos - 2. Lista enfermedades (Demencia, Bipolaridad, Epilepsia o Esquizofrenia) - 3. Diccionario que contiene un Dataframe para cada enfermedad. Dichos DataFrames almacenan la - información sobre la proximidad observada de cada fármaco a la enfermedad (proximity_files) - 4. Diccionario que contiene un Dataframe para cada enfermedad. Dichos DataFrames almacenan la - información sobre la la proximidad aleatoria media y su desviación estándar de cada fármaco a - la enfermedad (proximity_random_files) - 5. Archivo con información sobre las relaciones entre fármacos y enfermedades (arch) - """ - - combinaciones = list(product(enfermedades, farmacos)) #todas las combinaciones enfermedad-fármaco posibles - df_enfermedades_farmacos = pd.DataFrame(combinaciones, columns=['Enfermedades', 'Fármacos']) #DataFrame a partir de las combinaciones - df_enfermedades_farmacos['Tratamiento'] = df_enfermedades_farmacos.apply(lambda row: determinar_tratamiento(row, arch), axis=1) - #Añado la columna Tratamiento - - filas_combinadas = [] #fila vacía en la que añadiré cada fila combinada de los dos DataFrames de entrada - - for index, row in df_enfermedades_farmacos.iterrows(): #itero sobre las filas y columnas del DataFrame creado - enfermedad = row['Enfermedades'] #selecciona cada fila de la columna Enfermedades - farmaco = row['Fármacos'] #selecciona cada fila de la columna Fármacos - tratamiento = row['Tratamiento'] #selecciona cada fila de la columna Tratamiento - - #Obtengo el archivo de proximidad correspondiente a cada enfermedad - if enfermedad in proximity_files: - df_proximidad = proximity_files[enfermedad] - - # Buscar el farmaco en el archivo de proximidad y obtener el valor dc - #Busco cada fármaco en el DataFrame con los valores de proximidad observada para cada enfermedad - filtro = (df_proximidad['Fármacos'] == farmaco) - if filtro.any(): #si se encuentra el fármaco en el DataFrame - dc = df_proximidad[filtro]['dc'].values[0] #guardo su valor de proximidad a la enfermedad (dc) - - #Obtengo el archivo de proximidad correspondiente a cada enfermedad - df_proximidad_random = proximity_random_files[enfermedad] - - #Busco cada fármaco en el DataFrame con los valores de proximidad aleatoria para cada enfermedad - filtro_random = (df_proximidad_random['Fármacos'] == farmaco) - if filtro_random.any(): #si se encuentra el fármaco en el DataFrame - dc_mean = df_proximidad_random[filtro_random]['dc_mean'].values[0] #guardo su valor de proximidad aleatoria media (dc_mean) - dc_std = df_proximidad_random[filtro_random]['dc_std'].values[0] #guardo su valor de desviación de la proximidad aleatoria (dc_std) - - # Añado la fila a la lista - filas_combinadas.append({'Enfermedades': enfermedad, 'Fármacos': farmaco, 'Tratamiento': tratamiento, 'dc': dc, 'dc_mean': dc_mean, 'dc_std': dc_std}) - - # Crear el DataFrame con todos los datos combinados - df_combinado = pd.DataFrame(filas_combinadas) - df_combinado['dc_zscore'] = (df_combinado['dc'] - df_combinado['dc_mean']) / df_combinado['dc_std'] #añado una columna con el valor del zscore - - return df_combinado - -# ================================================================================= - -def rep_prox(df_combinado, nombre_enf): - """ - Esta función representa en un boxplot la distribución de la cercanía y a una enfermedad y - la distribución de su z-score para el grupo de fármacos que se emplean para tratar dicha - enfermedad y el grupo de fármacos que no se emplean para su tratamiento (unkwown) - - Datos de entrada: - 1. df_combinado: Dataframe combinado con los fármacos, su cercanía observada, su cercanía aleatoria media, - la devsiación estándar de la proximidad aleatoria, su z-score, una columna que indica la enfermedad - (la demencia, epilepsia, la bipolaridad o la esquizofrenia) y otra columna que indica si el fármaco - se usa para el tratamiento de la enfermedad en su misma fila. - 2. nombre_enf: Nombre de la enfermedad - """ - # Filtro los datos para generar dos nuevos dataframes, uno con los datos de los fármacos que se emplean como tratamiento de la enfermedad, y otro con los datos para el resto de fármacos - farmacos_con_enf = df_combinado[(df_combinado['Enfermedades'] == nombre_enf) & (df_combinado['Tratamiento'] == 'yes')] - farmacos_sin_enf = df_combinado[(df_combinado['Enfermedades'] == nombre_enf) & (df_combinado['Tratamiento'] == 'unknown')] - - combined_data = pd.concat([farmacos_con_enf.assign(Tratamiento='Tratamiento'), farmacos_sin_enf.assign(Tratamiento='Unkwown')]) - - # Combino los dos conjuntos de datos en un mismo subplot - fig, axes = plt.subplots(1, 2, figsize=(14, 6)) # Creo un subplot con 1 fila y 2 columnas - - # Represento el boxplot con ambas distribuciones de la proximidad - sns.boxplot(x='Tratamiento', y='dc', data=combined_data, hue='Tratamiento', ax=axes[0], palette={'Tratamiento': '#FF7A7A', 'Unkwown': '#79C4FF'}, dodge=False, medianprops=dict(linewidth=2), legend=False) - axes[0].set_ylabel('Cercanía ($\mathregular{d_c}$)', fontsize=12) - axes[0].set_xlabel('') - for label in axes[0].get_xticklabels(): - label.set_fontsize(12) - - # Represento el boxplot con ambas distribuciones de la proximidad - sns.boxplot(x='Tratamiento', y='dc_zscore', data=combined_data, hue='Tratamiento', ax=axes[1], palette={'Tratamiento': '#FF7A7A', 'Unkwown': '#79C4FF'}, dodge=False, medianprops=dict(linewidth=2), legend=False) - axes[1].set_ylabel('Proximidad [z-score ($\mathregular{d_c}$)]', fontsize=12) - axes[1].set_xlabel('') - for label in axes[1].get_xticklabels(): - label.set_fontsize(12) - - plt.suptitle(str(nombre_enf), fontsize=20, y=0.98, fontweight='bold', style='italic') - - - plt.tight_layout() # Ajusto la disposición del subplot para evitar superposiciones - plt.show() - -# ================================================================================= - -def targets_modulo(df_combinado, targets, lcc_files): - """ - Esta función permite obtener un DataFrame con las siguientes columnas: - 1. Enfermedades (Demencia, Bipolaridad, Epilepsia o Esquizofrenia) - 2. Fármacos - 3. Tratamiento: columna que indica si el el fármaco de la columna 2 trata a la enfermedad - de la columna 1 ("yes" en caso afirmativo, "unkwown" en el caso contrario - 4. Valor de proximidad a la Enfermedad de la columna 1 - 5. Proximidad aleatoria media a la Enfermedad de la columna 1 - 6. Desviación estándar de en las proximidades aleatorias a la Enfermedad de la columna 1 - 7. Z-Score de la proximidad observada (indicada en la columna 3) en comparación con - la proximidad aleatoria media (en la columna 4) y la desviación estándar de la - proximidad aleatoria (columna 5) - 8. Target en módulo: indica si el fármaco en de la columna 2 presenta alguna de sus - proteínas diana en el módulo de la enfermedad en la columna 1. - - Datos de entrada: - 1. df_combinado: DataFrame que contiene las 7 primeras columnas del archivo que se - obtiene como resultado (enfermedades, fármacos, tratamiento, dc, dc_mean, dc_std, dc_zscore) - 2. targets: DataFrame con la lista de proteínas diana de cada fármaco - 3. lcc_files: diccionario con el nombre de la enfermedad (key) y la lista de proteínas que - forman parte de su módulo (values). - """ - - targets_modulo = [] # lista para almacenar si el fármaco de la columna 2 en cada fila tiene una proteína diana en el módulo de la enfermedad de la columna 1 situada en su misma fila. - - # Itero sobre cada fila del DataFrame df_combinado - for index, row in df_combinado.iterrows(): - farmaco = row['Fármacos'] #selecciono cada fila de la columna Fármacos - enfermedad = row['Enfermedades'] #selecciono cada fila de la columna Enfermedades - - # Obtengo los targets de cada fármaco según el DataFrame de targets - farmaco_targets = set(targets[targets['Fármacos'] == farmaco]['Dianas'].iloc[0]) - - # Obtengo el módulo (lcc) de la enfermedad desde el diccionario de lcc_files - lcc_enf = lcc_files[enfermedad] - - # Verifico si alguno de los targets está en el módulo (lcc) de la enfermedad - resultado_farmaco = 'Sí' if farmaco_targets.intersection(lcc_enf) else 'No' - - # Agrego el resultado a la lista de resultados - targets_modulo.append(resultado_farmaco) - - # Añado la lista de resultados como una nueva columna del DataFrame df_combinado - df_combinado['Target en módulo'] = targets_modulo - - return df_combinado - -# ================================================================================= -- 2.24.1