Guía de Aprendizaje: R para Bioinformática

Módulos 1 y 2 — Fundamentos, Ecosistema y Estructura de Datos

Enlace web: https://rpubs.com/daniloceschin/Rbioinfo-EjerMod1y2

Asignatura: Bioinformática
Carrera: Licenciatura en Genética
Institución: IUCBC – CIMETSA, Córdoba, Argentina
Docente: Dr. Danilo G. Ceschin


Ejercicios Integradores

Los ejercicios están ordenados de menor a mayor dificultad dentro de cada bloque. Trabajá con RStudio abierto y ejecutá cada línea a medida que avanzás. Los comentarios con # → indican el resultado esperado.


Bloque A — R como calculadora y primeras asignaciones

(Módulo 1, sección 1.1 — primera_sesion.R)

A1. Calculá las siguientes expresiones y guardá cada resultado en un objeto con nombre descriptivo:

# a) La longitud de una secuencia de ADN de 1500 pares de bases,
#    expresada en kilobases (1 kb = 1000 pb)

# b) Si un gen ocupa 0.0023% del genoma humano (3.2 × 10^9 pb),
#    ¿cuántas pares de bases ocupa ese gen?

# c) El logaritmo en base 10 de 1000, de 10000 y de 0.001
#    ¿Qué patrón observás en los resultados?

# d) La raíz cuadrada de 144 y el cuadrado de 12
#    ¿Qué relación hay entre ambos resultados?

A2. Usá los objetos creados para operar entre ellos:

# Definí:
n_genes_humanos  <- 20000   # número aproximado de genes en el genoma humano
n_genes_analizados <- 350   # genes en un panel de secuenciación

# a) ¿Qué porcentaje del total representa el panel?
# b) Si cada gen tiene en promedio 1.2 kb, ¿cuántas kb totales cubre el panel?
# c) Guardá el porcentaje en un objeto llamado "cobertura_pct" y mostralo

Bloque B — Tipos de datos y objetos

(Módulo 1, sección 1.4 — primera_sesion.R)

B1. Creá objetos de distintos tipos y verificá su clase:

# Creá los siguientes objetos y verificá su clase con class():
gen_nombre   <- "BRCA1"
longitud_pb  <- 81188
n_exones     <- 23L
es_oncogen   <- FALSE
calidad_seq  <- "Alta"

# a) ¿Cuáles son numéricos? ¿Cuáles son character? ¿Cuáles son logical?
# b) ¿Qué diferencia hay entre longitud_pb y n_exones?
#    Hint: typeof()
# c) ¿Qué devuelve is.numeric(gen_nombre)?
#    ¿Y is.character(gen_nombre)? ¿Por qué?

B2. Explorá la coerción de tipos:

# Intentá estas conversiones y explicá qué ocurre en cada caso:
as.numeric("3.14")        # ¿funciona?
as.numeric("BRCA1")       # ¿funciona?
as.numeric(TRUE)          # ¿qué valor devuelve?
as.numeric(FALSE)         # ¿qué valor devuelve?
as.character(23L)         # ¿qué clase tiene el resultado?

# ¿Qué aprendés sobre la jerarquía de tipos en R?

B3. Trabajá con NA:

# Un vector con valores de calidad de secuenciación (Phred score),
# donde algunos datos están faltantes:
calidad <- c(38, 35, NA, 40, 32, NA, 37, 39)

# a) Calculá la media. ¿Qué ocurre?
# b) Calculá la media ignorando los NA
# c) ¿Cuántos valores faltan? Hint: sum(is.na(...))
# d) ¿En qué posiciones están los NA? Hint: which(is.na(...))

Bloque C — Factores

(Módulo 1, sección 1.4 y segunda_sesion.R)

C1. Un experimento tiene tres condiciones con 4 réplicas cada una:

# a) Creá un vector con los grupos del experimento:
#    4 réplicas de "Control", 4 de "Tratamiento_A", 4 de "Tratamiento_B"
#    Hint: rep()

# b) Convertilo a factor y verificá con class() e is.factor()

# c) ¿Cuáles son los niveles (levels)?

# d) ¿Cuántas réplicas hay por condición? Hint: table()

# e) Redefiní el factor con los niveles en este orden:
#    c("Control", "Tratamiento_A", "Tratamiento_B")
#    ¿Por qué importa que "Control" sea el primer nivel?

C2. Usá gl() para generar el diseño de un experimento de secuenciación:

# Un experimento tiene 3 condiciones experimentales,
# cada una con 3 réplicas biológicas

# a) Generá el factor usando gl()
# b) Asigná las etiquetas: "WT", "KO_gen1", "KO_gen2"
# c) Verificá con table() que cada grupo tiene 3 réplicas
# d) ¿Cuál es el nivel de referencia (primer nivel)?

Bloque D — Vectores y operaciones

(segunda_sesion.R — vectores)

D1. Trabajá con datos de longitudes de secuencias:

# Longitudes (en pb) de 8 genes de interés
longitudes <- c(1200, 850, 3400, 560, 2100, 4800, 980, 1650)
genes      <- c("GenA","GenB","GenC","GenD","GenE","GenF","GenG","GenH")
names(longitudes) <- genes

# a) ¿Cuál es la longitud total sumada de los 8 genes?
# b) ¿Cuál es la longitud media? ¿Y la mediana?
# c) Convertí las longitudes a kilobases (dividí por 1000)
# d) ¿Cuántos genes tienen más de 1.5 kb? Hint: sum(longitudes_kb > 1.5)
# e) ¿Cuáles son los nombres de esos genes? Hint: names(longitudes_kb)[...]
# f) Ordená los genes de mayor a menor longitud

D2. Selección y modificación de elementos:

longitudes <- c(1200, 850, 3400, 560, 2100, 4800, 980, 1650)

# a) Extraé el primer y el último elemento
# b) Extraé los elementos en las posiciones 2, 4 y 6
# c) Extraé todos los elementos excepto el tercero
# d) Reemplazá el valor 560 (posición 4) por 610
# e) ¿Cuál es el gen más largo? Hint: which.max()
# f) ¿Cuál es el gen más corto? Hint: which.min()

D3. Operaciones vectorizadas con datos de expresión génica:

# Valores de expresión (escala lineal) de 6 genes en una muestra:
expresion_lineal <- c(245, 12, 1890, 56, 3400, 780)
nombres_genes    <- c("Gen1","Gen2","Gen3","Gen4","Gen5","Gen6")

# En bioinformática es común trabajar con escala logarítmica
# para comprimir rangos muy grandes de valores

# a) Calculá log2(expresion_lineal)
#    ¿Por qué crees que se prefiere log2 sobre log10 en este contexto?

# b) Calculá log2(expresion_lineal + 1)
#    ¿Para qué sirve el "+1"? ¿Qué pasaría si un valor fuera 0?

# c) ¿Qué genes tienen expresión lineal por encima de la media?
# d) ¿Cuántos son?

Bloque E — Matrices

(segunda_sesion.R — matrices)

E1. Creá y explorá una matriz de datos de secuenciación:

# Cobertura promedio (número de veces que cada posición fue secuenciada)
# de 4 muestras en 5 regiones genómicas de interés

coberturas <- c(45, 32, 67, 28, 55,   # muestra 1
                41, 38, 70, 31, 60,   # muestra 2
                50, 29, 65, 25, 52,   # muestra 3
                48, 35, 72, 30, 58)   # muestra 4

regiones  <- c("Reg1","Reg2","Reg3","Reg4","Reg5")
muestras  <- c("M1","M2","M3","M4")

# a) Creá la matriz con las regiones como filas y muestras como columnas
#    Hint: matrix(..., nrow=5, byrow=FALSE, dimnames=list(regiones, muestras))

# b) ¿Qué región tiene la mayor cobertura media? Hint: apply(..., 1, mean)
# c) ¿Qué muestra tiene la mayor cobertura media? Hint: apply(..., 2, mean)
# d) ¿Cuál es la cobertura mínima en toda la matriz? ¿En qué posición está?
# e) Extraé la submatriz con solo las muestras M1 y M3

E2. Usá la matriz del zinc del ejercicio de clase con nombres de filas/columnas:

zinc <- matrix(
  c(0.43, 0.27, 0.57, 0.53, 0.70,
    0.42, 0.24, 0.39, 0.41, 0.61),
  nrow = 5,
  dimnames = list(
    c("Norte","Sur","Este","Oeste","Centro"),
    c("fondo","superficie")
  )
)

# a) ¿En qué zona hay mayor concentración de zinc en el fondo?
# b) ¿En qué zona la diferencia entre fondo y superficie es mayor?
#    Hint: creá una nueva columna con la diferencia
# c) Calculá la media de zinc en fondo y en superficie por separado
#    Hint: apply() o colMeans()
# d) ¿La concentración media es mayor en el fondo o en la superficie?

Bloque F — Listas

(segunda_sesion.R — listas)

F1. Creá una lista que represente la información de un gen:

# Construí una lista llamada "gen_BRCA1" con estos elementos:
# - nombre: "BRCA1"
# - cromosoma: "chr17"
# - longitud_pb: 81188
# - n_exones: 23
# - es_supresor_tumoral: TRUE
# - codigos_enfermedad: c("Cáncer de mama", "Cáncer de ovario")

# a) Creá la lista con list()
# b) ¿Cuántos elementos tiene? Hint: length()
# c) Accedé al nombre del gen con $
# d) Accedé al número de exones con [[]]
# e) Accedé al mismo elemento usando su posición numérica
# f) ¿Qué diferencia hay entre gen_BRCA1["n_exones"] y gen_BRCA1[["n_exones"]]?
#    Hint: compará class() de cada resultado

F2. Trabajá con una lista de resultados (como los que devuelven las funciones estadísticas):

# Generá dos vectores con medidas de longitud de genes
# en dos especies distintas:
set.seed(42)
longitudes_humano  <- rnorm(20, mean = 2500, sd = 800)
longitudes_raton   <- rnorm(20, mean = 2200, sd = 750)

# Realizá un test de comparación de medias:
resultado <- t.test(longitudes_humano, longitudes_raton)

# a) ¿Qué tipo de objeto es "resultado"? Hint: class()
# b) ¿Es una lista? Hint: is.list()
# c) ¿Qué elementos contiene? Hint: names()
# d) Extraé el p-valor con $
# e) ¿La diferencia es estadísticamente significativa (p < 0.05)?
# f) Extraé el intervalo de confianza. ¿Qué nos dice?

Bloque G — Data Frames

(segunda_sesion.R — data frames)

G1. Creá un data frame con información de muestras de secuenciación:

# Construí el siguiente data frame llamado "muestras":

# SampleID  | Especie        | Condicion | Reads_millones | Calidad_RIN
# -----------------------------------------------------------------
# "S01"     | "H.sapiens"    | "Control" | 45.2           | 8.9
# "S02"     | "H.sapiens"    | "Control" | 51.3           | 9.1
# "S03"     | "H.sapiens"    | "KO"      | 47.8           | 8.7
# "S04"     | "H.sapiens"    | "KO"      | 49.1           | 8.4
# "S05"     | "M.musculus"   | "Control" | 38.4           | 7.9
# "S06"     | "M.musculus"   | "KO"      | 41.2           | 8.2

# a) Creá el data frame. Asegurate de que "Condicion" sea un factor
#    con niveles c("Control","KO")

# b) Verificá la estructura con str(). ¿Qué tipo tiene cada columna?

# c) ¿Cuántas muestras hay por especie? Hint: table()

# d) Extraé la columna de reads con $

# e) ¿Cuál es la media de reads en muestras de H.sapiens?
#    Hint: muestras$Reads_millones[muestras$Especie == "H.sapiens"]

G2. Filtrá y modificá el data frame:

# Usando el data frame "muestras" del ejercicio anterior:

# a) Extraé solo las muestras de condición "KO"

# b) Extraé solo las muestras con RIN >= 8.5

# c) Extraé las muestras de H.sapiens con condición "Control"

# d) Agregá una nueva columna "Calidad_ok" que sea TRUE si RIN >= 8.5
#    y FALSE en caso contrario
#    Hint: muestras$Calidad_ok <- muestras$Calidad_RIN >= 8.5

# e) Usá str() y summary() sobre el data frame completo.
#    ¿Qué información útil te dan?

Bloque H — Ejercicio integrador final

H1. Este ejercicio combina todos los conceptos de los dos módulos:

# Tenés los siguientes datos de un pequeño experimento genómico.
# 6 genes fueron medidos en 3 condiciones (2 réplicas cada una):

genes      <- c("GenA","GenB","GenC","GenD","GenE","GenF")
longitud   <- c(1200, 3400, 850, 2100, 4800, 980)    # en pb
cromosoma  <- c("chr1","chr3","chr1","chr7","chr12","chr3")
es_conocido <- c(TRUE, TRUE, FALSE, TRUE, FALSE, TRUE)

# Mediciones de expresión (escala lineal) en 3 condiciones, 2 réplicas:
# Las columnas son: ctrl_1, ctrl_2, trat_1, trat_2, ko_1, ko_2

expresion <- matrix(
  c(245,  260,  890,  910,   45,   50,   # GenA
    12,    15,   11,   13,   10,   14,   # GenB
    1890, 1950, 1900, 1870, 1800, 1920,  # GenC
    56,    60,  210,  195,   25,   30,   # GenD
    3400, 3200,  150,  180, 3500, 3300,  # GenE
    780,  810,  790,  760,  800,  820),  # GenF
  nrow = 6, byrow = TRUE,
  dimnames = list(
    genes,
    c("ctrl_1","ctrl_2","trat_1","trat_2","ko_1","ko_2")
  )
)

# a) ¿Cuántos genes y cuántas muestras tiene la matriz?

# b) Calculá la expresión media de cada gen en cada condición:
#    media_ctrl = promedio de ctrl_1 y ctrl_2
#    media_trat = promedio de trat_1 y trat_2
#    media_ko   = promedio de ko_1 y ko_2

# c) Creá un data frame "resumen" con columnas:
#    gen, longitud, cromosoma, es_conocido, media_ctrl, media_trat, media_ko

# d) Agregá una columna "cambio_trat" con la diferencia: media_trat - media_ctrl
#    ¿Qué genes aumentaron su expresión con el tratamiento?

# e) Convertí "cromosoma" a factor. ¿Cuántos genes hay en cada cromosoma?

# f) Guardá el data frame en un archivo:
#    write.csv(resumen, "resumen_experimento.csv", row.names = FALSE)

Recursos Adicionales

Documentación oficial

Libros de acceso libre

Comunidad


Guía elaborada para Bioinformática — Licenciatura en Genética
IUCBC – CIMETSA · Córdoba, Argentina · 2026
Dr. Danilo G. Ceschin