Volver a la lista

Visualización de datos biológicos mediante Python.

Cómo dibujar curvas de supervivencia de Kaplan-Meier, gráficos de dispersión y mapas de calor de expresión génica con Python matplotlib.

Intermedio
|
120min
|
Verificado (2026-06)
matplotlibKaplan-Meiervolcano plotheatmapAnálisis de supervivenciaDEG
Progreso0/12 (0%)

Visualización de datos biológicos con Python

Al finalizar este tema

Con matplotlib, podrá crear tres tipos de gráficos que se utilizan habitualmente en la investigación biológica: curvas de supervivencia, gráficos de dispersión (volcano plots) y mapas de calor.


Introducción a matplotlib: primer gráfico

matplotlib es una de las bibliotecas de visualización más utilizadas en Python. plt.plot() Permite generar gráficos con una sola línea de código.

python
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
# Curva de crecimiento celular (crecimiento exponencial)
hours = np.array([0, 2, 4, 6, 8, 10, 12, 24])
cell_count = np.array([1000, 1200, 1800, 3200, 6000, 11000, 22000, 500000])
fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(hours, cell_count, "o-", color="#2E86AB", linewidth=2, markersize=6)
ax.set_xlabel("Time (hours)", fontsize=12)
ax.set_ylabel("Cell Count", fontsize=12)
ax.set_title("Cell Growth Curve", fontsize=14, fontweight="bold")
ax.set_yscale("log")
ax.grid(True, alpha=0.3)
fig.tight_layout()
fig.savefig("growth_curve.png", dpi=150)
plt.close(fig)
assert len(hours) == 8
assert cell_count[-1] == 500000
print("growth_curve.png guardado correctamente")

Gráfico de barras: Comparación del contenido de GC de varios genes

python
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
def calculate_gc(seq: str) -> float:
seq = seq.upper()
return (seq.count("G") + seq.count("C")) / len(seq) * 100
genes = {
"BRCA1": "ATGGATTTATCTGCTCTTCGCGTTGAAGAAGTACAAAATGTC",
"TP53": "ATGGAGGAGCCGCAGTCAGATCCTAGCGTGAGTTTGCTGTGA",
"EGFR": "ATGCGACCCTCCGGGACGGCCGGGGCAGCGCTCCTGGCGCTG",
"MYC": "ATGCCCCTCAACGTTAGCTTCACCAACAGGAACTATGACCTCG",
"KRAS": "ATGACTGAATATAAACTTGTGGTAGTTGGAGCTGGTGGCGTAG",
}
names = list(genes.keys())
gc_values = [calculate_gc(seq) for seq in genes.values()]
colors = ["#E74C3C" if gc > 60 else "#2E86AB" for gc in gc_values]
fig, ax = plt.subplots(figsize=(8, 5))
bars = ax.bar(names, gc_values, color=colors, edgecolor="white", linewidth=0.5)
ax.axhline(y=60, color="#E74C3C", linestyle="--", alpha=0.5, label="GC > 60% threshold")
ax.set_ylabel("GC Content (%)", fontsize=12)
ax.set_title("GC Content by Gene", fontsize=14, fontweight="bold")
ax.legend()
ax.set_ylim(0, 100)
fig.tight_layout()
fig.savefig("gc_bar_chart.png", dpi=150)
plt.close(fig)
assert len(gc_values) == 5
assert all(0 <= gc <= 100 for gc in gc_values)
print(f"GC values: {[f'{gc:.1f}%' for gc in gc_values]}")

Curva de supervivencia de Kaplan-Meier

El análisis de supervivencia es una de las visualizaciones más importantes en los ensayos clínicos. Compara las tasas de supervivencia entre dos grupos: el grupo de tratamiento y el grupo de control.

python
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(42)
# Generar datos clínicos simulados
n_patients = 50
treatment_times = np.sort(np.random.exponential(scale=24, size=n_patients))
control_times = np.sort(np.random.exponential(scale=16, size=n_patients))
def kaplan_meier(times, max_time=48):
times = times[times <= max_time]
n = len(times)
km_times = [0]
km_survival = [1.0]
at_risk = n
for t in sorted(set(times)):
events = np.sum(times == t)
survival = km_survival[-1] * (1 - events / at_risk)
km_times.append(t)
km_survival.append(survival)
at_risk -= events
return np.array(km_times), np.array(km_survival)
t_times, t_surv = kaplan_meier(treatment_times)
c_times, c_surv = kaplan_meier(control_times)
fig, ax = plt.subplots(figsize=(8, 5))
ax.step(t_times, t_surv, where="post", color="#2E86AB", linewidth=2, label="Treatment (n=50)")
ax.step(c_times, c_surv, where="post", color="#E74C3C", linewidth=2, label="Control (n=50)")
ax.fill_between(t_times, t_surv, step="post", alpha=0.1, color="#2E86AB")
ax.fill_between(c_times, c_surv, step="post", alpha=0.1, color="#E74C3C")
ax.set_xlabel("Time (months)", fontsize=12)
ax.set_ylabel("Survival Probability", fontsize=12)
ax.set_title("Kaplan-Meier Survival Curve", fontsize=14, fontweight="bold")
ax.legend(fontsize=11, loc="lower left")
ax.set_xlim(0, 48)
ax.set_ylim(0, 1.05)
ax.grid(True, alpha=0.3)
fig.tight_layout()
fig.savefig("kaplan_meier.png", dpi=150)
plt.close(fig)
assert t_surv[0] == 1.0
assert c_surv[0] == 1.0
assert len(t_times) > 1
print("kaplan_meier.png guardado correctamente")

Gráfico de volcán: visualización de genes con expresión diferencial

Un gráfico de volcán permite visualizar de forma rápida los genes que presentan cambios significativos en su expresión a partir de datos de secuenciación de ARN (RNA-seq). El eje X representa la magnitud del cambio (log2 fold change) y el eje Y, la significancia estadística (-log10 del valor p).

python
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(42)
n_genes = 500
log2fc = np.random.normal(0, 1.5, n_genes)
pvalues = 10 ** (-np.abs(log2fc) * np.random.uniform(0.5, 3, n_genes))
fc_threshold = 1.0
p_threshold = 0.05
colors = []
for fc, p in zip(log2fc, pvalues):
if p < p_threshold and fc > fc_threshold:
colors.append("#E74C3C") # Regulación al alza
elif p < p_threshold and fc < -fc_threshold:
colors.append("#2E86AB") # Regulación a la baja
else:
colors.append("#CCCCCC") # No significativo
neg_log_p = -np.log10(pvalues)
fig, ax = plt.subplots(figsize=(8, 6))
ax.scatter(log2fc, neg_log_p, c=colors, s=10, alpha=0.7, edgecolors="none")
ax.axhline(-np.log10(p_threshold), color="gray", linestyle="--", alpha=0.5)
ax.axvline(fc_threshold, color="gray", linestyle="--", alpha=0.5)
ax.axvline(-fc_threshold, color="gray", linestyle="--", alpha=0.5)
n_up = sum(1 for c in colors if c == "#E74C3C")
n_down = sum(1 for c in colors if c == "#2E86AB")
ax.set_xlabel("log₂ Fold Change", fontsize=12)
ax.set_ylabel("-log₁₀ p-value", fontsize=12)
ax.set_title(f"Volcano Plot (↑{n_up} ↓{n_down} DEGs)", fontsize=14, fontweight="bold")
ax.grid(True, alpha=0.2)
fig.tight_layout()
fig.savefig("volcano_plot.png", dpi=150)
plt.close(fig)
assert n_up > 0
assert n_down > 0
print(f"Al alza: {n_up}, a la baja: {n_down}")

Mapa de calor: patrones de expresión génica

El mapa de calor compara los niveles de expresión génica en varias muestras mediante el uso de colores.

python
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(42)
gene_names = ["BRCA1", "TP53", "EGFR", "MYC", "KRAS", "PTEN", "RB1", "APC"]
sample_names = ["Normal_1", "Normal_2", "Tumor_1", "Tumor_2", "Tumor_3"]
expression = np.random.randn(len(gene_names), len(sample_names))
expression[:, 2:] += np.random.uniform(0.5, 2.0, (len(gene_names), 3))
fig, ax = plt.subplots(figsize=(8, 6))
im = ax.imshow(expression, cmap="RdBu_r", aspect="auto", vmin=-3, vmax=3)
ax.set_xticks(range(len(sample_names)))
ax.set_xticklabels(sample_names, rotation=45, ha="right", fontsize=10)
ax.set_yticks(range(len(gene_names)))
ax.set_yticklabels(gene_names, fontsize=10)
ax.set_title("Gene Expression Heatmap", fontsize=14, fontweight="bold")
fig.colorbar(im, ax=ax, label="Z-score", shrink=0.8)
fig.tight_layout()
fig.savefig("heatmap.png", dpi=150)
plt.close(fig)
assert expression.shape == (8, 5)
print(f"Heatmap: {expression.shape[0]} genes × {expression.shape[1]} samples")

Prueba tú mismo (Ejemplo desvanecido)

Completa los espacios en blanco para completar el diagrama de dispersión.

Completar espaciospython
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
x = [1, 2, 3, 4, 5]
y = [2.1, 3.9, 6.2, 7.8, 10.1]
fig, ax = plt.subplots()
ax.(x, y, color="blue")
ax.set_xlabel("Concentration")
ax.set_ylabel("")
fig.savefig("scatter.png")
plt.close(fig)

Errores comunes y soluciones

P: El gráfico no se muestra y UserWarning: Matplotlib is currently using agg

En entornos de servidor (Colab, SSH, etc.), llama a matplotlib.use("Agg") antes de importar plt y guarda los archivos usando fig.savefig() en lugar de plt.show().

P: El título en coreano se muestra incorrectamente

Agrega plt.rcParams['font.family'] = 'NanumGothic'. En Colab, debes reiniciar el entorno de ejecución después de !apt-get install -y fonts-nanum.

P: El gráfico está recortado y las etiquetas no son visibles

Llama a fig.tight_layout() antes de savefig(). La mayoría de los problemas de recorte se resuelven.


En el siguiente texto, aprenderás a clasificar datos de expresión génica mediante aprendizaje automático.

💬 Preguntas y comentarios

0 comentarios

Puedes publicar sin iniciar sesión. Los comentarios de invitados no pueden editarse ni eliminarse después.

0/2000

Cargando...