BioData Insights

Conceptos Básicos de Python para Ciencia de Datos

Introduce la sintaxis, tipos de datos y estructuras de control de Python, sentando las bases para el análisis de datos biológicos y la toma de decisiones informada.

¿Qué es Python y por qué usarlo para Ciencia de Datos?

Python es un lenguaje de programación de alto nivel, conocido por su sintaxis simple y legible, que se asemeja al lenguaje humano. Esto lo hace ideal para principiantes. En el mundo empresarial y científico, su popularidad se debe a su vasto ecosistema de librerías, que son como cajas de herramientas especializadas que nos permiten realizar tareas complejas (como análisis estadístico o visualización de datos) sin tener que programar todo desde cero.

Para la ciencia de datos, Python es la herramienta dominante porque nos permite realizar todo el ciclo de vida de un proyecto: desde la recolección y limpieza de datos hasta la creación de modelos predictivos y visualizaciones interactivas. Aprender Python es el primer paso para poder transformar datos crudos (como mediciones de campo o resultados de un secuenciador) en decisiones informadas y estratégicas, una habilidad crucial en la Industria 4.0 y en la investigación moderna.

Variables y Tipos de Datos Fundamentales

Una variable es un espacio en la memoria del ordenador donde guardamos un valor para usarlo más tarde. Cada variable tiene un nombre único. Los datos que guardamos pueden ser de diferentes tipos:

  • Cadena (str): Para almacenar texto. Se define con comillas simples o dobles. Ej: el nombre de un gen, una especie de planta.
  • Entero (int): Para números enteros, sin decimales. Ej: el número de hojas de una planta, la longitud de una secuencia de ADN.
  • Flotante (float): Para números con decimales. Ej: el pH de una muestra, la temperatura de un cultivo.
  • Booleano (bool): Representa dos valores de verdad: Verdadero (True) o Falso (False). Ej: si una planta presenta o no una enfermedad.

Entender los tipos es vital, ya que define qué operaciones podemos hacer. Por ejemplo, podemos sumar dos números, pero no sumar un número y una cadena de texto directamente. Python es un lenguaje de tipado dinámico, lo que significa que no necesitas declarar el tipo de una variable; el intérprete lo infiere por ti.


# Nota: Este código está listo para ser copiado y ejecutado en un notebook de Google Colab.

# Asignamos el texto "Citocromo C" a la variable 'nombre_secuencia'.
# Python infiere que este es un tipo de dato Cadena (string) por las comillas.
nombre_secuencia = "Citocromo C"

# Asignamos el número entero 104 a la variable 'longitud'.
# Python infiere que es un Entero (integer).
longitud = 104

# Asignamos el número decimal 12384.47 a la variable 'peso_molecular'.
# Python infiere que es un Flotante (float) por el punto decimal.
peso_molecular = 12384.47

# Asignamos el valor booleano True a la variable 'es_proteina'.
# Los booleanos solo pueden ser True o False (con mayúscula inicial).
es_proteina = True

# La función print() muestra valores en la pantalla.
# Usamos una f-string (cadena formateada, con una 'f' antes de las comillas)
# para combinar texto y variables de una manera muy legible y eficiente.
print(f"Secuencia: {nombre_secuencia}, Longitud: {longitud} aminoácidos.")
print(f"Peso Molecular: {peso_molecular} Dalton.")
print(f"¿Es una proteína? {es_proteina}")

# >> Salida:
# Secuencia: Citocromo C, Longitud: 104 aminoácidos.
# Peso Molecular: 12384.47 Dalton.
# ¿Es una proteína? True
    
Estructuras de Datos: Listas y Diccionarios

Para manejar colecciones de datos, Python nos ofrece estructuras muy útiles. Las dos más comunes son las listas (colecciones ordenadas de elementos, que se pueden modificar) y los diccionarios (colecciones no ordenadas de pares "clave-valor", optimizadas para búsquedas rápidas).

En bioinformática, una lista podría contener una serie de mediciones de expresión génica de un experimento, mientras que un diccionario podría almacenar los metadatos de una muestra biológica (ID de la muestra, fecha de recolección, organismo, etc.), donde cada dato tiene un nombre claro (la clave).


# Nota: Este código está listo para ser copiado y ejecutado en un notebook de Google Colab.

# --- Listas: Colecciones ordenadas y mutables ---
# Una lista se define con corchetes []. Contiene una colección ordenada de elementos.
# Aquí, almacenamos los IDs de varios genes de interés.
ids_genes_resistencia = ["gen-R1a", "gen-Rpi-blb1", "gen-Rx"]

# Para acceder a un elemento de la lista, usamos su índice (posición, empezando en 0).
primer_gen = ids_genes_resistencia[0]
print("Primer gen de la lista:", primer_gen)
# >> Salida: Primer gen de la lista: gen-R1a

# Podemos añadir un nuevo elemento al final de la lista con el método .append().
ids_genes_resistencia.append("gen-Lr34")
print("Lista actualizada de genes:", ids_genes_resistencia)
# >> Salida: Lista actualizada de genes: ['gen-R1a', 'gen-Rpi-blb1', 'gen-Rx', 'gen-Lr34']


# --- Diccionarios: Pares Clave-Valor ---
# Un diccionario se define con llaves {}. Almacena pares clave-valor.
# Es ideal para datos donde cada valor tiene un nombre descriptivo (la clave).
# Aquí guardamos información sobre una muestra de secuenciación.
metadatos_muestra = {
  "id_muestra": "A-42",             # Clave "id_muestra" con valor "A-42"
  "organismo": "Solanum tuberosum", # Clave "organismo" con valor "Solanum tuberosum"
  "fecha_recoleccion": "2023-10-26",
  "profundidad_sec": 30             # Clave "profundidad_sec" con valor 30
}

# Para acceder a un valor, usamos su clave entre corchetes.
organismo_de_la_muestra = metadatos_muestra["organismo"]
print("Organismo de la muestra:", organismo_de_la_muestra)
# >> Salida: Organismo de la muestra: Solanum tuberosum

# Podemos añadir un nuevo par clave-valor simplemente asignándolo.
metadatos_muestra["tecnologia"] = "Illumina NovaSeq"
print("Metadatos actualizados:", metadatos_muestra)
# >> Salida: Metadatos actualizados: {'id_muestra': 'A-42', 'organismo': 'Solanum tuberosum', 'fecha_recoleccion': '2023-10-26', 'profundidad_sec': 30, 'tecnologia': 'Illumina NovaSeq'}
    
Lógica Condicional y Bucles: El Corazón de la Automatización

Las estructuras de control dirigen el flujo de un programa. Con la sentencia if-elif-else, podemos ejecutar diferentes bloques de código según si se cumple o no una condición. Con el bucle for, podemos repetir una acción para cada elemento de una secuencia (como una lista).

Estas herramientas son la base de la algoritmia y nos permiten implementar lógica compleja. Por ejemplo, en un análisis de fitopatología, podríamos usar un bucle para revisar una lista de mediciones de infección y una estructura condicional para clasificar cada planta como "sana", "moderadamente infectada" o "severamente infectada" y contarlas automáticamente. Esto es infinitamente más rápido y menos propenso a errores que hacerlo manualmente.


# Nota: Este código está listo para ser copiado y ejecutado en un notebook de Google Colab.

# Creamos una lista con los niveles de severidad de una enfermedad en 5 plantas (escala 0-100).
severidad_enfermedad = [15.5, 82.1, 45.3, 9.8, 95.0]
# Creamos contadores para llevar la cuenta de cada categoría.
conteo_bajo = 0
conteo_medio = 0
conteo_alto = 0


# El bucle 'for' recorre cada elemento de la lista 'severidad_enfermedad'.
# En cada pasada (iteración), el elemento actual se guarda en la variable 'nivel'.
for nivel in severidad_enfermedad:
  # Imprimimos el nivel que estamos evaluando en esta iteración.
  print(f"Evaluando nivel: {nivel}")
  # La sentencia 'if' evalúa si la condición (nivel > 80) es verdadera.
  if nivel > 80:
    # Si es verdadera, se ejecuta este bloque de código.
    print(f"-> Clasificación: ALTO. Es un caso crítico.")
    conteo_alto += 1 # Incrementamos el contador de casos altos.
  # 'elif' (else if) evalúa otra condición si la anterior fue falsa.
  elif nivel > 40:
    # Si nivel no es > 80 pero es > 40, se ejecuta este bloque.
    print(f"-> Clasificación: MEDIO. Requiere monitoreo.")
    conteo_medio += 1 # Incrementamos el contador de casos medios.
  # 'else' se ejecuta si ninguna de las condiciones anteriores fue verdadera.
  else:
    print(f"-> Clasificación: BAJO. Condición aceptable.")
    conteo_bajo += 1 # Incrementamos el contador de casos bajos.

# Una vez terminado el bucle, imprimimos el resumen.
print("\n--- Resumen del Lote de Plantas ---")
print(f"Plantas con severidad BAJA: {conteo_bajo}")
print(f"Plantas con severidad MEDIA: {conteo_medio}")
print(f"Plantas con severidad ALTA: {conteo_alto}")

# >> Salida:
# Evaluando nivel: 15.5
# -> Clasificación: BAJO. Condición aceptable.
# Evaluando nivel: 82.1
# -> Clasificación: ALTO. Es un caso crítico.
# Evaluando nivel: 45.3
# -> Clasificación: MEDIO. Requiere monitoreo.
# Evaluando nivel: 9.8
# -> Clasificación: BAJO. Condición aceptable.
# Evaluando nivel: 95.0
# -> Clasificación: ALTO. Es un caso crítico.
#
# --- Resumen del Lote de Plantas ---
# Plantas con severidad BAJA: 2
# Plantas con severidad MEDIA: 1
# Plantas con severidad ALTA: 2