Códigos para descarga:     [ .Rmd ]     [ .R ]

Introducción

Para empezar, se dará una suave introducción al lenguaje de programación estadística R (R Development Core Team, 2022), específico para nuestros fines. Esto resolverá las cuestiones prácticas para seguir la corriente del razonamiento. En particular, se explica brevemente cómo instalar R y Bioconductor, cómo obtener ayuda y cómo realizar cálculos y gráficos sencillos. Dado que muchos cálculos se realizan esencialmente sobre vectores de datos, se ofrecen varias ilustraciones básicas al respecto. Con respecto a las expresiones genéticas, los vectores de datos se colocan uno debajo del otro para formar una matriz de datos con los genes como filas y los pacientes como columnas. La idea de una matriz de datos se explica ampliamente y se ilustra con varios ejemplos. Un ejemplo más amplio consiste en los datos clásicos de Golub et al. (1999), que se analizarán con frecuencia para ilustrar algunos de los procedimientos estadísticos, en otros casos se crean los datos según el tópico considerado..

¿Qué es R?

R es un potente entorno estadístico y lenguaje de programación para el análisis y la visualización de datos. El paquete asociado Bioconductor y el paquete CRAN ofrecen muchos paquetes R adicionales para el análisis estadístico de datos para una amplia gama de áreas de investigación. El software R es gratuito y funciona en todos los sistemas operativos comunes.

¿Porqué usar R?

  • Entorno estadístico y lenguaje de programación completo
  • Funciones y estructuras de datos eficientes para el análisis de datos
  • Potentes gráficos
  • Acceso a un número creciente de paquetes de análisis
  • El lenguaje más utilizado en bioinformática
  • Es el estándar para la minería de datos y el análisis bioestadístico
  • Ventajas técnicas: gratuito, de código abierto, disponible para todos los sistemas operativos

Libros y Documentación

  • Using R for Introductory Statistics (John Verzani, 2004) -
  • Bioinformatics and Computational Biology Solutions Using R and Bioconductor (Gentleman et al., 2005)

Ambientes de trabajo

Algunos entornos de trabajo de R con soporte de resaltado de sintaxis y utilidades para enviar código a la consola de R:

Repositorios

  • CRAN (>16.000 packages) : análisis general de datos -
  • Bioconductor (>2.000 packages) biociencias-análisis de datos -
  • Omegahat (>90 packages) programando interfaces -
  • RStudio y sus paquetes -

Instalación de R, RStudio y librerías de R

Puedes descargar R libremente, basta buscar las direcciiones que abajo se muestran según su sistema operativo favorito (Windows, Linux o MacOS) y simplemente siga las instrucciones. Tras un poco de paciencia, debería poder iniciar R (Ihaka & Gentleman, 1996), tras lo cual se abrirá una pantalla con el indicador > en la consola. La entrada y la salida de R se mostrarán en estilo de escritura literal.

  1. Instale R en su sistema operativo CRAN.

  2. Instale RStudio desde RStudio.

  3. Instale librerías del CRAN desde la consola asi como:

    install.packages(c("pkg1", "pkg2")) 
    install.packages("pkg.zip", repos=NULL)
  1. Instale paquetes de Bioconductor haciendo:

    if (!requireNamespace("BiocManager", quietly = TRUE))
        install.packages("BiocManager") 
    BiocManager::version() 
    BiocManager::install(c("pkg1", "pkg2")) 
if (!require("BiocManager", quietly = TRUE))
    install.packages("BiocManager")
#BiocManager::install("limma")
#BiocManager::install("multtest")
  1. Para más detalles consulte Bioc Install page y el paquete BiocInstaller.

Desplazándose

Comportamiento de arranque y cierre

  • Arranque R: Las versiones de R GUI, incluyendo RStudio, bajo Windows y Mac OS X pueden ser abierto haciendo doble clic en sus iconos. Alternativamente, se puede iniciar escribiendo R en un terminal.

  • Arranque/Cierre: El entorno de R está controlado por archivos ocultos en el directorio de inicio: .RData, .Rhistory y .Rprofile (opcional).

  • Cerrando R:

q()  
Save workspace image? [y/n/c]:
  • Nota: Cuando se responde con y, entonces todo el espacio de trabajo de R se escribirá en el archivo .RData que puede llegar a ser muy grande. A menudo es mejor seleccionar n , porque una práctica de trabajo mucho mejor es guardar un protocolo de análisis en un archivo fuente R o Rmd. De esta manera uno puede regenerar rápidamente todos los conjuntos de datos y objetos necesarios en una futura sesión.

Sintáxis Básica

Crear un objeto con el operador de asignación<- o =

objeto <- ...

Sintaxis general de los comandos de R

objeto <- function_name(arguments) 
objeto <- object[arguments] 

En lugar del operador de asignación se puede utilizar el operador assign

assign("x", function(arguments))

Para simplificar el encadenamiento de varias operaciones, dplyr (magrittr) provee el operador %>% (pipe), donde x %>% f(y) resulta en f(x, y). De esta forma se pueden encadenar múltiples operaciones escribiéndolas de izquierda a derecha o de arriba a abajo. Esto hace que el código sea fácil de escribir y código legible. Los detalles sobre esto se proporcionan en el tutorial de dplyr here.

... %>% ...

Solicitando ayuda

?function_name

Cargar librería o paquete

library("mi_librería") 

Lista de funciones definidas por una librería o paquete

library(help="mi_librería")

Cargar el manual de la librería (archivo PDF o HTML)

vignette("mi_librería") 

Ejecutar un script de R desde R

source("mi_script.R")

Tipos de objetos de datos en R

Escalares

El tipo de objeto más simple es un escalar. Un escalar es un objeto con un valor. Para crear un objeto de datos escalar, basta con asignar un valor a una variable mediante el operador de asignación “<-” o “=”. Ejemplo:

#crea un objeto de datos escalar x con valor 5
x<- 5
#create scalar data object y with value 2
y<- 2

Con objetos de datos escalares de modo numérico, R es una gran calculadora. Puede manipular objetos escalares en R y realizar todo tipo de cálculos algebraicos.

#algunas manipulaciones sobre objetos escalares x e y
z<-x+y
z
## [1] 7
x-y
## [1] 3
x*y+2
## [1] 12

Por supuesto, los datos también pueden ser lógicos o de caracteres. Los datos “lógicos” pueden introducirse simplemente como T o F (sin comillas).

correctaLogica<-T
correctaLogica
## [1] TRUE
incorrectaLogica<-"T"
incorrectaLogica
## [1] "T"

Los datos de carácter deben ir siempre entre comillas (simples o dobles).

single<-'singleQuote'
double<-"doubleQuote"
single
## [1] "singleQuote"
double
## [1] "doubleQuote"
# saldrá error si metes caracteres sin comillas
try(ejemplo<-error)
## Error in try(ejemplo <- error) : objeto 'error' no encontrado

La función “mode()” (nombre de variable) le indicará la clase de una variable.

mode(x)
## [1] "numeric"
mode(correctaLogica)
## [1] "logical"
mode(incorrectaLogica)
## [1] "character"

Vectores

Por supuesto, la potencia de R no reside en su capacidad para trabajar con datos escalares simples sino en su capacidad para trabajar con grandes conjuntos de datos. Los vectores son los objetos de datos probablemente más utilizados en R . Un vector puede definirse como un conjunto de escalares dispuestos en una matriz unidimensional.

Básicamente, un escalar es un vector unidimensional. Los valores de datos en un vector son todos del mismo tipo, pero un vector puede contener datos de cualquier tipo. Los vectores pueden introducirse utilizando la función “c()” (o “combinar valores” en un vector) .

vector<-c(2,5,5,3,3,6,2,3,5,6,3)
vector
##  [1] 2 5 5 3 3 6 2 3 5 6 3

Otra forma de crear un vector es hacerlo a partir de otros vectores:

v1<-c(1,2,3)
v2<-c(4,5,6)

Puede realizar todo tipo de operaciones en vectores, una característica muy potente y útil de R, que se utilizará a lo largo de estas notas.

z<-v1+v2
z 
## [1] 5 7 9

Tenga en cuenta que si realiza operaciones en vectores con longitudes diferentes (no recomendado), el vector con la longitud más corta se recicla a la longitud del vector más largo, de modo que el primer elemento del vector más corto se añade a la longitud del vector más largo(una forma de fingir que tiene la misma longitud).

Aparecerá un mensaje de advertencia, pero le permitirá realizar la operación solicitada:

x1<-c(1,2,3)
x2<-c(3,4)
x3<-x1+x2
x3 
## [1] 4 6 6

También puede crear un vector uniendo vectores existentes con la función “c()”:

q<-c(v1,v2)
q
## [1] 1 2 3 4 5 6

Los vectores cuyas entradas son todas iguales pueden crearse fácilmente utilizando la función rep() (repetir):

x<-rep(3,7)
x
## [1] 3 3 3 3 3 3 3
carvec<-rep("ja",10)
carvec
##  [1] "ja" "ja" "ja" "ja" "ja" "ja" "ja" "ja" "ja" "ja"

Factores

Un factor es un tipo especial de vector de caracteres. En la mayoría de los casos, los datos de caracteres se utilizan para describir otros datos y no se utilizan en los cálculos. Sin embargo, para algunos cálculos se utilizan variables cualitativas. Para almacenar datos tipo caracter como variables cualitativas se utiliza un tipo de dato factor. Aunque la mayor parte de estas notas es cuantitativo, en algunas secciones utilizaremos variables cualitativas , sobre todo en el diseño experimental.

Puede crear un factor creando primero un vector de caracteres, y luego convirtiéndolo a un tipo de factor utilizando la función factor():

genotipo<-c("criolla","pastusa","otra")
genotipo<-factor(genotipo)

Observe que esto crea “niveles” basados en los valores de los factores (estos son los valores de las variables categóricas).

genotipo
## [1] criolla pastusa otra   
## Levels: criolla otra pastusa

Otra forma usual usa la función gl():

# una observación por nivel
prevalencia=gl(3,1,3,labels=c("alta","media","baja"))
prevalencia
## [1] alta  media baja 
## Levels: alta media baja
# cinco observaciones por nivel
prevalencias=gl(3,5,15,labels=c("alta","media","baja"))
prevalencias
##  [1] alta  alta  alta  alta  alta  media media media media media baja  baja  baja  baja  baja 
## Levels: alta media baja

Matrices y matrices

Las matrices son colecciones de valores de datos en dos dimensiones. En matemáticas las matrices tienen muchas aplicaciones, y se requiere un buen curso de álgebra lineal para apreciar plenamente la utilidad de las matrices.

Un array(arreglo) es una matriz de más de dos dimensiones. Formatear los datos como matrices y arrays proporciona una estructura de datos eficiente para realizar cálculos de una manera rápida y eficaz.

Para declarar una matriz en R, utilice la función matrix(), que toma como argumentos un vector de datos y parámetros de especificación para el número de filas y columnas y la forma de llenado. Vamos a declarar una matriz simple de 2 por 2.

mat1<-matrix(c(2,3,1,5),nrow=2,ncol=2)
mat1
##      [,1] [,2]
## [1,]    2    1
## [2,]    3    5

En estas notas no se presuponen conocimientos de matemáticas matriciales, y cuando sea necesario se proporcionará la información adecuada. Normalmente, los datos de una matriz son numéricos.

También se pueden crear fácilmente matrices especialmente estructuradas. Por ejemplo, crear una matriz matriz de 2 por 3 formada por solo unos:

unosmat<-matrix(1,nrow=2,ncol=3)
unosmat
##      [,1] [,2] [,3]
## [1,]    1    1    1
## [2,]    1    1    1

Si usted crea una matriz con un conjunto de números, por ejemplo 7 números, y usted especifica las columnas, por ejemplo 3 columnas, R recorrerá los números hasta que llene todo el espacio especificado en la matriz, dando un advertencia sobre longitudes de reemplazo desiguales:

matrix(c(1,2,3,4,5,6,7),ncol=3)
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    1
## [3,]    3    6    2

Listas

Las listas son los objetos de datos ” de todo”. Una lista, a diferencia de un vector, puede contener datos con diferentes clases bajo el mismo nombre de variable y englobar otros objetos de datos. Las listas son útiles para organizar la información. Crear una lista es muy sencilla; basta con utilizar la función list() para asignar a una variable los valores de la lista.

Tenga en cuenta que los valores de la lista se indexan con conjuntos de corchetes dobles, como \([[1]]\), en lugar de los conjuntos de corchetes simples utilizados por otros objetos de datos.

milista<-list(5,6,"siete", unosmat)
milista
## [[1]]
## [1] 5
## 
## [[2]]
## [1] 6
## 
## [[3]]
## [1] "siete"
## 
## [[4]]
##      [,1] [,2] [,3]
## [1,]    1    1    1
## [2,]    1    1    1

Marcos de datos - Dataframes

Los marcos de datos (df) son objetos de datos versátiles que puede utilizar en R. Puede pensar en un objeto marco de datos como en una hoja de cálculo. Cada columna del marco de datos es un vector. Dentro de cada vector, todos los elementos de datos deben ser del mismo tipo. Sin embargo, diferentes vectores pueden ser de diferentes clases. Todos los vectores de un df deben tener la misma longitud, esto no significa que no podrían existir datos faltantes.

mi_df <- data.frame(
  "entero" = 1:4, 
  "factor" = c("a", "b", "c", "d"), 
  "numero" = c(1.2, 3.4, 4.5, 5.6),
  "cadena" = as.character(c("a", "b", "c", "d"))
)

mi_df
##   entero factor numero cadena
## 1      1      a    1.2      a
## 2      2      b    3.4      b
## 3      3      c    4.5      c
## 4      4      d    5.6      d

Podemos usar __dim()_ en un data frame para conocer su dimensión

dim(mi_df)
## [1] 4 4

o names() para ver los nombres de las columnas

names(mi_df)
## [1] "entero" "factor" "numero" "cadena"

Si los vectores que usamos para construir el data frame no son del mismo largo, los datos no se reciclaran. Se nos devolverá un error.

try(data.frame(
  "entero" = 1:3, 
  "factor" = c("a", "b", "c", "d"), 
  "numero" = c(1.2, 3.4, 4.5, 5.6),
  "cadena" = as.character(c("a", "b", "c", "d"))
))
## Error in data.frame(entero = 1:3, factor = c("a", "b", "c", "d"), numero = c(1.2,  : 
##   arguments imply differing number of rows: 3, 4

También podemos coercionar esta matriz a un data frame. Creamos una matriz.

matriz <- matrix(1:12, ncol = 4)

Usamos as.data.frame() para coercionar una matriz a un data frame.

df <- as.data.frame(matriz)

Verificamos el resultado en la clase

class(df)
## [1] "data.frame"

Creación de un Marco de Datos Vacío en R

En algunos casos, podemos necesitar crear un DataFrame vacío en R con sólo los nombres de las columnas y los tipos de datos de las columnas y sin filas - para luego rellenarlo utilizando un bucle for. Para ello, aplicamos de nuevo la función data.frame(), como sigue:

df_vacio <- data.frame(rating=numeric(),
                                   animal=character(),
                                   country=character(),
                                   avg_sleep_hours=numeric())
print(df_vacio )
## [1] rating          animal          country         avg_sleep_hours
## <0 rows> (or 0-length row.names)

Revisando la estructura del df

dfs <- data.frame(col1 = 1:3, 
                 col2 = c("esto ", "es", "pasión"), 
                 col3 = c(TRUE, FALSE, TRUE), 
                 col4 = c(2.5, 4.2, pi), 
                 stringsAsFactors = FALSE) # para no convertir en factores las cols

str(dfs)
## 'data.frame':    3 obs. of  4 variables:
##  $ col1: int  1 2 3
##  $ col2: chr  "esto " "es" "pasión"
##  $ col3: logi  TRUE FALSE TRUE
##  $ col4: num  2.5 4.2 3.14

Añadir atributos a los df

Al igual que las matrices, los marcos de datos tienen un atributo de dimensión. Además, los df también pueden tener atributos adicionales como nombres de filas, nombres de columnas y comentarios. Podemos ilustrarlo con el marco de datos df.

attributes(dfs)
## $names
## [1] "col1" "col2" "col3" "col4"
## 
## $class
## [1] "data.frame"
## 
## $row.names
## [1] 1 2 3

Actualmente df no tiene nombres de fila pero podemos añadirlos con rownames():

rownames(dfs) <- c("fila", "fila2", "fila3")
dfs
##       col1   col2  col3     col4
## fila     1  esto   TRUE 2.500000
## fila2    2     es FALSE 4.200000
## fila3    3 pasión  TRUE 3.141593

También podemos cambiar los nombres de las columnas existentes utilizando colnames()

colnames(dfs) <- c("col_1", "col_2", "col_3", "col_4")
dfs
##       col_1  col_2 col_3    col_4
## fila      1  esto   TRUE 2.500000
## fila2     2     es FALSE 4.200000
## fila3     3 pasión  TRUE 3.141593

Por último, al igual que los vectores, las listas y las matrices, podemos añadir un comentario a un marco de datos sin que ello afecte a su funcionamiento (útil para explicar el conjunto de datos)

comment(dfs) <- "mi comentario"
dfs
##       col_1  col_2 col_3    col_4
## fila      1  esto   TRUE 2.500000
## fila2     2     es FALSE 4.200000
## fila3     3 pasión  TRUE 3.141593
attributes(dfs)
## $names
## [1] "col_1" "col_2" "col_3" "col_4"
## 
## $class
## [1] "data.frame"
## 
## $row.names
## [1] "fila"  "fila2" "fila3"
## 
## $comment
## [1] "mi comentario"

Trabajar con objetos de datos

Una vez que haya creado un objeto de datos, a menudo querrá realizar varias tareas. En esta sección se describen algunas tareas comunes para acceder y modificar objetos de datos existentes. Nos centraremos principalmente en los vectores y los marcos de datos, ya que éstos serán los objetos de datos más utilizados en estas notas, pero se pueden aplicar técnicas similares a otros objetos de datos.

Extraer elementos

Para extraer (también conocido como indexar o subinscribir) uno o más valores (más generalmente conocidos como elementos) de un vector utilizamos la notación de corchetes \([ ]\). El método general consiste en nombrar el objeto que se desea extraer y, a continuación, un conjunto de corchetes con un índice del elemento que se desea extraer contenido dentro de los corchetes. Este índice puede ser una posición o el resultado de una prueba lógica.

  • Índice posicional Para extraer elementos en función de su posición simplemente escribimos la posición dentro del \([ ]\). Por ejemplo, para extraer el 3er valor de mivec
mivec=c(seq(5,200,5))     
mivec[3]
## [1] 15

si desea almacenar este valor en otro objeto

val_3 <- mivec[3];val_3
## [1] 15

También podemos extraer más de un valor utilizando la función c() dentro de los corchetes. Aquí extraemos el \(1er\), \(5º\), \(6º\) y \(8º\) elemento del objeto mivec

mivec[c(1, 5, 6, 8)]
## [1]  5 25 30 40

O podemos extraer un rango de valores utilizando la notación \(:\) . Para extraer los valores del \(3º\) al \(8º\) elemento

mivec[3:8]
## [1] 15 20 25 30 35 40
  • Índice lógico Otra forma realmente útil de extraer datos de un vector es utilizar una expresión lógica como índice. Por ejemplo, para extraer todos los elementos con un valor superior a 170 en el vector mivec
v2=rnorm(20,10,1)
v2[v2 > 11]
## [1] 12.69776 11.41161 11.44475 11.11346

Aquí, la expresión lógica es v2 > 11 en R sólo extraerá aquellos elementos que satisfagan esta condición lógica. ¿Cómo funciona esto realmente? Si nos fijamos en la salida de sólo la expresión lógica sin los corchetes se puede ver que R devuelve un vector que contiene TRUE o FALSE que corresponden a si la condición lógica se cumple para cada elemento. En este caso sólo los elementos mayores a 11 y devuelve un TRUE ya que su valor es mayor que 11.

v2 > 11
##  [1] FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE
## [17] FALSE FALSE FALSE FALSE

Así que lo que R está haciendo realmente bajo el capó es equivalente a

v2[c(T,T,F,F,T,F,F,F,F,F,F,F,F,F,T,F,F,F,T,T)]
## [1]  9.396288 12.697763 10.185982 11.113461  9.975348  9.848532

y sólo se extraerán los elementos que sean TRUE.

Además de los operadores \(<\) y \(>\), también se pueden utilizar operadores compuestos para aumentar la complejidad de las expresiones. Por ejemplo, la expresión “mayor o igual que” es \(>=\). Para comprobar si un valor es igual a otro hay que utilizar el símbolo doble igual \(==\) y para “no igual a” se utiliza \(!=\) (el símbolo \(!\) significa “no”).

v2[v2 >=11]        
## [1] 12.69776 11.41161 11.44475 11.11346
v2[v2 < 11]         
##  [1]  9.396288 10.100939 10.185982 10.699051  9.878526 10.786267 10.556830 10.873774  9.673142
## [10]  9.402041  9.265940 10.226861 10.052045 10.531856  9.975348  9.848532
v2[v2 <= 11]       
##  [1]  9.396288 10.100939 10.185982 10.699051  9.878526 10.786267 10.556830 10.873774  9.673142
## [10]  9.402041  9.265940 10.226861 10.052045 10.531856  9.975348  9.848532
v2[v2 == 11.2]       
## numeric(0)
v2[v2 != 11.399282]        
##  [1]  9.396288 12.697763 11.411605 10.100939 10.185982 10.699051  9.878526 10.786267 10.556830
## [10] 10.873774  9.673142  9.402041  9.265940 11.444753 11.113461 10.226861 10.052045 10.531856
## [19]  9.975348  9.848532

También podemos combinar varias expresiones lógicas utilizando expresiones booleanas. En R el símbolo \(&\) significa AND y el símbolo \(|\) significa OR. Por ejemplo, para extraer valores en v2 que sean menores que 10 y mayores que 8

v3 <- v2[v2 < 10 & v2 > 8]
v3
## [1] 9.396288 9.878526 9.673142 9.402041 9.265940 9.975348 9.848532

o extraer valores en v2 que sean mayores que 6 o menores que 8

v4 <- v2[v2 > 6 | v2 < 8]
v4
##  [1]  9.396288 12.697763 11.411605 10.100939 10.185982 10.699051  9.878526 10.786267 10.556830
## [10] 10.873774  9.673142  9.402041  9.265940 11.444753 11.113461 10.226861 10.052045 10.531856
## [19]  9.975348  9.848532
  • Sustitución de elementos Podemos cambiar los valores de algunos elementos de un vector utilizando nuestra notación \([ ]\) en combinación con el operador de asignación \(<-\). Por ejemplo, para sustituir el \(4º\) valor de nuestro objeto v2 por 20
v2[4] <- 20
v2
##  [1]  9.396288 12.697763 11.411605 20.000000 10.185982 10.699051  9.878526 10.786267 10.556830
## [10] 10.873774  9.673142  9.402041  9.265940 11.444753 11.113461 10.226861 10.052045 10.531856
## [19]  9.975348  9.848532

También podemos sustituir más de un valor o incluso sustituir valores basándonos en una expresión lógica

v2[c(6, 7)] <- 10
v2
##  [1]  9.396288 12.697763 11.411605 20.000000 10.185982 10.000000 10.000000 10.786267 10.556830
## [10] 10.873774  9.673142  9.402041  9.265940 11.444753 11.113461 10.226861 10.052045 10.531856
## [19]  9.975348  9.848532
v2[v2 <= 10] <- 1
v2
##  [1]  1.00000 12.69776 11.41161 20.00000 10.18598  1.00000  1.00000 10.78627 10.55683 10.87377
## [11]  1.00000  1.00000  1.00000 11.44475 11.11346 10.22686 10.05205 10.53186  1.00000  1.00000
  • Ordenar elementos Además de extraer elementos concretos de un vector también podemos ordenar los valores contenidos en un vector. Para ordenar los valores de menor a mayor podemos utilizar la función sort()
vec_sort <- sort(v2)
vec_sort
##  [1]  1.00000  1.00000  1.00000  1.00000  1.00000  1.00000  1.00000  1.00000 10.05205 10.18598
## [11] 10.22686 10.53186 10.55683 10.78627 10.87377 11.11346 11.41161 11.44475 12.69776 20.00000

Para invertir la ordenación, de mayor a menor, podemos incluir el argumento decreasing = TRUE al utilizar la función sort()

vec_sort2 <- sort(v2, decreasing = TRUE)
vec_sort2
##  [1] 20.00000 12.69776 11.44475 11.41161 11.11346 10.87377 10.78627 10.55683 10.53186 10.22686
## [11] 10.18598 10.05205  1.00000  1.00000  1.00000  1.00000  1.00000  1.00000  1.00000  1.00000

o primero ordenar el vector utilizando la función sort() y luego invertir el vector ordenado utilizando la función rev(). Este es otro ejemplo de anidamiento de una función dentro de otra función.

vec_sort3 <- rev(sort(v2))
vec_sort3
##  [1] 20.00000 12.69776 11.44475 11.41161 11.11346 10.87377 10.78627 10.55683 10.53186 10.22686
## [11] 10.18598 10.05205  1.00000  1.00000  1.00000  1.00000  1.00000  1.00000  1.00000  1.00000

Aunque ordenar un único vector es divertido, quizás una tarea más útil sería ordenar un vector en función de los valores de otro vector. Para ello debemos utilizar la función order() en combinación con \([ ]\). Para demostrarlo, creemos un vector llamado altura que contenga la altura de 5 plantas y otro vector llamado genotipo que contenga los nombres de las variedades.

altura <- c(180, 155, 160, 167, 181)
altura
## [1] 180 155 160 167 181
genotipo <- c("J", "Ch", "H", "K", "A")
genotipo
## [1] "J"  "Ch" "H"  "K"  "A"

Nuestro objetivo es ordenar los genotipos en orden ascendente según su altura. Lo primero que haremos será utilizar la función order() con la variable altura para crear un vector llamado altura_ord

altura_ord <- order(altura)
altura_ord
## [1] 2 3 4 1 5
genotipo_ord <- genotipo[altura_ord]
genotipo_ord
## [1] "Ch" "H"  "K"  "J"  "A"

Seguramente estarás pensando: “¿para qué sirve esto? Bien, imagina que tienes un conjunto de datos que contiene dos columnas de datos y quieres ordenar cada columna. Si utilizas sort() para ordenar cada columna por separado, los valores de cada columna se desacoplarán entre sí. Usando order() en una columna, se crea un vector de índices posicionales de los valores de la columna en orden ascendente. Este vector puede ser usado en la segunda columna, como el índice de elementos que devolverá un vector de valores basado en la primera columna. (Importante para mantener correlaciones)

  • Vectorización Una de las grandes ventajas de las funciones de R es que la mayoría están vectorizadas. Esto significa que la función operará sobre todos los elementos de un vector sin necesidad de aplicar la función a cada elemento por separado. Por ejemplo, para multiplicar cada elemento de un vector por 5 podemos utilizar simplemente
vecx <- c(3, 5, 7, 1, 9, 20)
vecx * 5
## [1]  15  25  35   5  45 100
  • Datos que faltan En R, los datos que faltan se suelen representar con el símbolo \(NA\), que significa “No disponible”. Los datos pueden faltar por un montón de razones, tal vez su máquina se daño, tal vez usted se equivocó, tal vez el tiempo era demasiado malo para recoger datos en un día determinado, etc, etc. Los datos que faltan pueden ser una molestia, tanto desde el punto de vista de R como desde el punto de vista estadístico. Desde el punto de vista de R, los datos que faltan pueden ser problemáticos, ya que diferentes funciones tratan los datos que faltan de diferentes maneras. Por ejemplo, digamos que recogimos lecturas de la temperatura del aire durante 10 días, pero nuestro termómetro se rompió el día 2 y de nuevo el día 9, por lo que no tenemos datos para esos días.
temp  <- c(7.2, NA, 7.1, 6.9, 6.5, 5.8, 5.8, 5.5, NA, 5.5)
temp
##  [1] 7.2  NA 7.1 6.9 6.5 5.8 5.8 5.5  NA 5.5

Ahora queremos calcular la temperatura media de estos días utilizando la función mean()

mean_temp <- mean(temp)
mean_temp
## [1] NA

¿qué ha pasado aquí? ¿por qué la función mean() devuelve un \(NA\). En realidad, R está haciendo algo muy sensato (¡al menos en nuestra opinión!). Si a un vector le falta un valor, el único valor posible que devuelve al calcular la media es \(NA\). R no sabe que quizás quiera ignorar los valores \(NA\) (R no puede leer su mente, ¡todavía!). Afortunadamente, si miramos en el archivo de ayuda (utilice help(“mean”) y verá que hay un argumento na.rm = que se establece en \(FALSE\) por defecto.Si cambiamos este argumento por na.rm = TRUE cuando utilicemos la función mean() nos permitirá ignorar los valores \(NA\) al calcular la media

temp_media <- mean(temp, na.rm = TRUE)
temp_media
## [1] 6.2875

Buscando ayuda

Para acceder a la ayuda integrada de R y obtener información sobre cualquier función, basta con utilizar la función help(). Por ejemplo, para abrir la página de ayuda de nuestra amiga la función mean().

help("mean")

Aparece en la ventana

Ayuda

Hacemos clic en la opción de la librería base , pues puede notar que hay dos librerías diferentes que llaman a la Media Aritmética.

Media Aritmética

Ahora puede notar las otras opciones que tiene esta función:

  • x : los datos
  • trim: opción de truncado de la media en el rango (0,0.5)
  • na.rm: opción para remover faltantes en el cálculo de la media

Siempre será buena idea mirar el ejemplo que suele aparecer al final de la ayuda, en nuestro caso aparece:

x <- c(0:10, 50)
xm <- mean(x)
c(xm, mean(x, trim = 0.10))
## [1] 8.75 5.50

donde se generan 12 datos \(x\), se calcula su media y se guarda en \(xm\) y se guarda en un vector tanto la media completa como la truncada al \(10%\).El resultado muestra los dos valores.

Para solicitar la ayuda también pudo usarse “?mean”.

La función help() es útil si conoce el nombre de la función. Si no está seguro del nombre, pero puede recordar una palabra clave, entonces puede buscar en el sistema de ayuda de R utilizando la función help.search() o su equivalente con “??mean”.

Búsquedas relacionadas

Otra función útil es apropos(). Esta función puede utilizarse para listar todas las funciones que contienen una cadena de caracteres especificada. Por ejemplo, para encontrar todas las funciones con mean en su nombre

apropos("mean")
##  [1] ".colMeans"      ".rowMeans"      "colMeans"       "colMeans"       "diffmeanX"     
##  [6] "kmeans"         "mean"           "mean"           "mean.Date"      "mean.default"  
## [11] "mean.difftime"  "mean.POSIXct"   "mean.POSIXlt"   "mean_cl_boot"   "mean_cl_normal"
## [16] "mean_sdl"       "mean_se"        "mean_temp"      "meanX"          "rowMeans"      
## [21] "rowMeans"       "weighted.mean"

Una función extremadamente útil es RSiteSearch() que le permite buscar palabras clave y frases en las páginas de ayuda de funciones y viñetas de todos los paquetes de CRAN, y en las vistas de tareas de CRAN. Esta función le permite acceder al motor de búsqueda https://www.r-project.org/search.html directamente desde la Consola con los resultados mostrados en su navegador web. Por ejemplo “RSiteSearch(”hotelling”)”.

Tipos de Datos

R tiene seis tipos básicos de datos: numéricos, enteros, lógicos, complejos y de caracteres. Los más pendientes se darán cuenta de que sólo hemos enumerado cinco tipos de datos aquí, el último tipo de datos es raw que no cubriremos ya que no es útil en el \(99,99%\) de las veces. Tampoco trataremos los números complejos porque no tenemos imaginación para ello en este contexto.

*Los datos numéricos son números que contienen un decimal. En realidad, también pueden ser números enteros, pero lo pasaremos por alto.

  • Los números enteros son números sin decimales.

  • Los datos lógicos toman el valor de VERDADERO o FALSO. También hay otro tipo especial de datos lógicos llamados \(NA\) para representar valores perdidos.

  • Los datos carácter se utilizan para representar valores de cadena. Las cadenas de caracteres son como una palabra (o varias palabras). Un tipo especial de cadena de caracteres es un factor, que es una cadena pero con atributos adicionales (como niveles o un orden). Hablaremos de los factores más adelante.

R es (normalmente) capaz de distinguir automáticamente entre diferentes clases de datos por su naturaleza y el contexto en el que se utilizan, aunque debe tener en cuenta que R no puede leer su mente y puede que tenga que decirle explícitamente a R cómo desea tratar un tipo de datos. Puede averiguar el tipo (o clase) de cualquier objeto utilizando la función class().

num <- 2.2
class(num)
## [1] "numeric"
char <- "hello"
class(char)
## [1] "character"
logi <- TRUE
class(logi)
## [1] "logical"

Alternativamente, puede preguntar si un objeto es de una clase específica utilizando una prueba lógica. La familia de funciones is.classOfData devolverá un VERDADERO o un FALSO.

is.numeric(num)
## [1] TRUE
is.character(num)
## [1] FALSE
is.character(char)
## [1] TRUE
is.logical(logi)
## [1] TRUE

A veces puede ser útil poder cambiar la clase de una variable utilizando la familia de funciones de coerción as.className, aunque hay que tener cuidado al hacerlo ya que se pueden obtener resultados inesperados (véase lo que ocurre a continuación cuando intentamos convertir una cadena de caracteres en numérica).

# número a caracter
class(num)
## [1] "numeric"
num_char <-  as.character(num)
num_char
## [1] "2.2"
class(num_char)
## [1] "character"
# caracter a número
class(char)
## [1] "character"
char_num <- as.numeric(char)
## Warning: NAs introduced by coercion

Coerción: A la fuerza

He aquí una tabla resumen de algunas de las funciones lógicas de comprobación y coerción que tiene a su disposición.

Pruebas lógicas

Operadores y cálculos

Operadores de comparación: ==, !=, <, >, <=, >=

1==1
## [1] TRUE

Operadores lógicos para operaciones booleanas: AND: &, OR: |, NOT: !

x <- 1:10; y <- 10:1
x > y & x > 5
##  [1] FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE

Cálculos básicos

Para buscar funciones matemáticas, vea el índice de funciones en here

x + y
##  [1] 11 11 11 11 11 11 11 11 11 11
sum(x) #suma
## [1] 55
mean(x) #promedio
## [1] 5.5
apply(iris[1:6,1:3], 1, mean) #aplicando la media por filas a las filas 1 hasta 6 y columnas 1 a la 3 
##        1        2        3        4        5        6 
## 3.333333 3.100000 3.066667 3.066667 3.333333 3.666667

Lectura y escritura de datos externos

Importación de datos tabulares

Importación de un archivo de excel

dfxlsx <- read.delim("midata.xlsx") #debemos proveer la ruta

La importación desde hojas de Excel funciona bien con readxl. Nota: trabajar con archivos delimitados por tabulaciones o comas es más flexible y preferible para los flujos de trabajo de análisis automatizados.

library("readxl")
mysheet <- read_excel("C:/Users/57316/Desktop/notebooks/disenniosR.xlsx")
mysheet
## # A tibble: 72 × 6
##    yield block irrigation density fertilizer roots_depth
##    <dbl> <chr> <chr>      <chr>   <chr>            <dbl>
##  1    90 A     control    low     N                   10
##  2    95 A     control    low     P                   11
##  3   107 A     control    low     NP                  12
##  4    92 A     control    medium  N                   11
##  5    89 A     control    medium  P                   12
##  6    92 A     control    medium  NP                  14
##  7    81 A     control    high    N                   13
##  8    92 A     control    high    P                   13
##  9    93 A     control    high    NP                  15
## 10    80 A     irrigated  low     N                   12
## # … with 62 more rows

Exportar data.frame a hoja de excel

library(openxlsx)
a=rnorm(6,3,0.3)
b=runif(6,1,2)
dft=data.frame(a=a,b=b)
write.table(dft, file="C:/Users/57316/Desktop/notebooks/midf.xlsx")

Exportar objeto R

milista <- list(C1=iris[,1], C2=iris[,2]) 
saveRDS(milista, "C:/Users/57316/Desktop/notebooks/milista.rds")

Importar objeto R

milista2 <- readRDS("C:/Users/57316/Desktop/notebooks/milista.rds")

Copiar y Pegar en R

En sistemas Windows/Linux

read.delim("clipboard") 

En sistemas Mac OS X

read.delim(pipe("pbpaste")) 

Copiar y Pegar de R

###En sistemas Windows/Linux

write.table(iris, "clipboard", sep="\t", col.names=NA, quote=FALSE) 

###En sistemas Mac OS X

zz <- pipe('pbcopy', 'w')
write.table(iris, zz, sep="\t", col.names=NA, quote=FALSE)
close(zz) 

###Ejecutando un código R pre-existente

En este caso, solo en esta ruta aparece un código personal para hacer remuestreo, pero sin necesidad de abrir el archivo, puedo ejecutar esta función almacenada para correrala en otro archivo. Si alguno de ustedes lo intenta debe hacerlo con una función propia y en su propia ruta.

source("C:/Users/57316/Desktop/scripst_R/bootstrapymas.R", local = knitr::knit_global())