R Markdown
En R existen distintos tipos de datos simples predefinidos:
numeric: Es el tipo de los números. Secuencia de dígitos
(pueden incluir el - para negativos y el punto como separador de
decimales) que representan números. Por ejemplo,
1,-2.0, 3.1415 o
4.5e3. Por defecto, cualquier número que se teclee tomará
este tipo.
integer: Es el tipo de los números enteros. Secuencia de
dígitos sin separador de decimales que representan un número entero. Por
ejemplo 1 o -2. Son una subclase del tipo de
datos numérico.
double: Es el tipo de los números reales. Secuencia de
dígitos que incluyen decimales separados por punto. Por ejemplo
3.1415 o -2.0. Son una subclase del tipo de
datos numérico.
character: Es el tipo de las cadenas de caracteres.
Secuencia de caracteres alfanuméricos que representan texto. Se escriben
entre comillas simples o dobles. Por ejemplo "Hola" o
'Hola'.
logical: Es el tipo de los booleanos. Puede tomar
cualquiera de los dos valores lógicos TRUE (verdadero) o
FALSE (falso). También se pueden abreviar como
T o F.
NA: Se utiliza para representar datos desconocidos o
perdidos. Aunque en realidad es un dato lógico, puede considerarse con
un tipo de dato especial.
NULL: Se utiliza para representar la ausencia de datos.
La principal diferencia con NA es que NULL
aparece cuando se intenta acceder a un dato que no existe, mientras que
NA se utiliza para representar explícitamente datos
perdidos en un estudio.
Para averiguar el tipo de un dato se puede utilizar la siguiente función:
class(x): Devuelve el tipo del dato x.
## speed dist
## Min. : 4.0 Min. : 2.00
## 1st Qu.:12.0 1st Qu.: 26.00
## Median :15.0 Median : 36.00
## Mean :15.4 Mean : 42.98
## 3rd Qu.:19.0 3rd Qu.: 56.00
## Max. :25.0 Max. :120.00
También pueden utilizarse las siguientes funciones que devuelven un booleano:
is.numeric(x): Devuelve el booleanoTRUEsi \(x\) es del tiponumeric.is.double(x): Devuelve el booleanoTRUEsi \(x\) es del tipodouble.is.integer(x): Devuelve el booleanoTRUEsi \(x\) es del tipointeger.is.character(x): Devuelve el booleanoTRUEsi \(x\) es del tipocharacter.is.logical(x): Devuelve el booleanoTRUEsi \(x\) es del tipological.is.na(x): Devuelve el booleanoTRUEsi \(x\) es del tipoNA.is.null(x): Devuelve el booleanoTRUEsi \(x\) es del tipoNULL.
Conversión de tipos
En muchas ocasiones es posible convertir un dato de un tipo a otro distinto. Para ello se usan las siguientes funciones:
as.numeric(x): Convierte el dato dexal tiponumericsiempre que sea posible o tenga sentido la conversión. Para convertir una cadena en un número, la cadena tiene que representar un número. El valor lógicoTRUEse convierte en 1 y elFALSEen 0.
as.integer(x): Convierte el dato dexal tipointegersiempre que sea posible o tenga sentido la conversión. Para convertir una cadena en un número entero, la cadena tiene que representar un número entero. El valor lógicoTRUEse convierte en 1 y elFALSEen 0.
as.character(x): Convierte el tipo de dato dexal tipocharactersimplemente añadiendo comillas.
as.logical(x): Convierte el tipo de dato dexal tipo lógico. Para datos numéricos, el 0 se convierte enFALSEy cualquier otro número enTRUE.Para cadenas se obtieneNAexcepto para las cadenas"TRUE"y"true"que se convierten aTRUEy las cadenas"FALSE"y"false"que se convierten aFALSE.
El tipo NA no se puede convertir a ningún otro tipo pues
representa la ausencia del dato. Lo mismo ocurre con
NULL.
Operaciones con R. R como una calculadora lógica.
Los siguientes operadores permiten realizar las clásicas operaciones aritméticas entre datos numéricos:
x + y: Devuelve la suma dexey.x - y: Devuelve la resta dexey.x * y: Devuelve el producto dexey.x / y: Devuelve el cociente dexey.x %% y: Devuelve el resto de la división entera dexey.x ^ y: Devuelve la potenciaxelevado ay.
Operadores relacionales
Comparan dos números y devuelven un valor lógico.
x == y: DevuelveTRUEsi el númeroxes igual que el númeroy, yFALSEen caso contrario.x > y: DevuelveTRUEsi el númeroxes mayor que el númeroy, yFALSEen caso contrario.x < y: DevuelveTRUEsi el númeroxes menor que el númeroy, yFALSEen caso contrario.x >= y: DevuelveTRUEsi el númeroxes mayor o igual que el númeroy, yFALSEen caso contrario.x <= y: DevuelveTRUEsi el númeroxes menor o igual a que el númeroy, yFALSEen caso contrario.x != y: DevuelveTRUEsi el númeroxes distinto del númeroy, yFALSEen caso contrario.
Funciones y constantes numéricas
Las siguientes constantes y funciones matemáticas también están ya predefinidas.
pi: Devuelve el número \(\pi\).sqrt(x): Devuelve la raíz cuadrada dex.abs(x): Devuelve el valor absoluto dex.round(x, n): Devuelve el redondeo dexandecimales.exp(x): Devuelve la exponencial dex(\(e^x\)).log(x): Devuelve el logaritmo neperiano dex.sin(x): Devuelve el seno del ánguloxen radianes.cos(x): Devuelve el coseno del ánguloxen radianes.tan(x): Devuelve la tangente del ánguloxen radianes.asin(x): Devuelve el arcoseno dex.acos(x): Devuelve el arcocoseno dex.atan(x): Devuelve el arcotangente dex.
Funciones para cadenas de caracteres
Existen muchas funciones para cadenas de texto pero las más comunes son:
nchar(c): Devuelve el número de caracteres de la cadena.paste(x, y, ..., sep=s): Concatena las cadenasx,y, etc. separándolas por la cadenas. Por defecto la cadena de separación es un espacio en blanco.substr(c, start=i, stop=j): Devuelve la subcadena de la cadenacdesde la posiciónihasta la posiciónj. El primer carácter de una cadena ocupa la posición 1.tolower(c): Devuelve la cadena que resulta de convertir la cadenaca minúsculas.toupper(c): Devuelve la cadena que resulta de convertir la cadenaca mayúsculas.
Operaciones de comparación de cadena
x == y: DevuelveTRUEsi la cadenaxes igual que la cadenay, yFALSEen caso contrario.x > y: DevuelveTRUEsi la cadenaxsucede a la cadenay, yFALSEen caso contrario.x < y: DevuelveTRUEsi la cadenaxantecede a la cadenay, yFALSEen caso contrario.x >= y: DevuelveTRUEsi la cadenaxsucede o es igual a la cadenay, yFALSEen caso contrario.x <= y: DevuelveTRUEsi la cadenaxantecede o es igual a la cadenay, yFALSEen caso contrario.x != y: DevuelveTRUEsi la cadenaxes distinta de la cadenay, yFALSEen caso contrario.
Tabla de verdad
| x | y | !x | x & y | x | y |
|---|---|---|---|---|
| FALSE | FALSE | TRUE | FALSE | FALSE |
| FALSE | TRUE | TRUE | FALSE | TRUE |
| TRUE | FALSE | FALSE | FALSE | TRUE |
| TRUE | TRUE | FALSE | TRUE | TRUE |
Tipos de datos estructurados
Los tipos estructurados de datos, a diferencia de los simples, son colecciones de datos con una determinada estructura. En R existen varios tipos tipos estructurados de datos que pueden clasificarse de acuerdo a su dimensión y a si son homogéneos (todos sus elementos son del mismo tipo) o heterogéneos.
- Los “vectores” son representaciones cuya dimensión es uno, todos sus elementos son numéricos (homogémeos)
- Si los elementos coleccionados en un arreglo unidimensional (dimensión = 1), estaremos hablando de “listas”
- Si el arreglo es bidimensional (dimensión = 2) y, toda la información contenida es del mismo tipo, se le llama “matriz” al arreglo.
- Si en el arreglo se es contenida información de distintos tipos (factores, numéricos, etc.) y el arreglo es bidimensional, se está hablando de un arreglo llamado “Data frame” (marco de datos)
- Si la dimensión del arreglo de datos estructurados es mayor a 2, se le llamará “array”. Estos guardan similitudes con los llamados “tensores”.
Para averiguar del tipo de arreglo de datos se está trabajando, se
debe de utilizar la la instrucción str(x).
Creación de vectores
Para construir un vector se utiliza la función de combinación
c():
c(x1, x2, ...): Devuelve el vector formado por los
elementos x1, x2, etc. También es posible
utilizar el operador : para generar un vector de números
enteros consecutivos:
x:y: Devuelve el vector de números enteros consecutivos
desde x hasta y.
Es posible asignar un nombre a cada elemento de un vector. Los
nombres son etiquetas de texto que se asocian a cada elemento. Para
asociar un nombre a un elemento se utiliza la sintaxis
nombre = valor, donde nombre es una cadena de
caracteres y valor es el elemento del vector. (Similar a
los diccionarios en Python)
names(x): Devuelve un vector de cadenas de caracteres
con los nombres de los elementos del vector x.
Coerción de elementos
Puesto que los elementos de un vector tienen que ser del mismo tipo,
cuando se crea un vector con datos de distintos tipos, la función
c() los convertirá al mismo tipo, lo que se conoce como
coerción de tipos. La coerción se produce de los tipos menos flexibles a
los más flexibles: logical < integer <
double < character.
Acceso a los elementos de un vector
Para acceder a los elementos de un vector se utiliza un índice. Como
veremos a continuación, este índice puede ser entero, lógico o de cadena
de caracteres y se indica siempre entre corchetes [ ] a
continuación del vector.
Los elementos de un vector están ordenados y el acceso más simple a
ellos es mediante su número de orden, es decir, indicando entre
corchetes [ ] el entero que corresponde a su número de
orden. Se puede acceder simultáneamente a varios elementos mediante un
vector con sus números de orden.
Cuando se utiliza un índice lógico, se obtienen los elementos
correspondientes a las posiciones donde está el valor booleano
TRUE.
Esta forma de acceder es útil cuando se genera el vector de índices mediante operadores relacionales. Cuando se aplica un operador relacional a un vector se obtiene otro vector lógico que resulta de aplicar el operador relacional a cada uno de los elementos del vector. De esta manera se puede realizar filtros para obtener los elementos de un vector que cumplen una determinada condición.
Si los elementos de un vector tienen nombre, es posible acceder a ellos usando sus nombres como índices. Esto aplica para los arreglos tipo lista o los arreglos tipo Data frame.
Pertenencia a un vector
Para comprobar si un valor en particular es un elemento de un vector
se puede utilizar el operador %in%:
## [1] TRUE
Modificación de los elementos de un vector
Para modificar uno o varios elementos de un vector basta con acceder a esos elementos y usar el operador de asignación para asignar nuevos valores.
v[i] <- x: Asigna el dato x a la
posición i del vector v.
v[c(i,j,...)] <- x: Asigna el dato x a las
posiciones i, j, etc. del vector
v.
Añadir elementos a un vector
Para añadir nuevos elementos a un vector pueden usarse las siguientes funciones:
c(x, y): Devuelve el vector que resulta de añadir al
vector x los elementos del vector y.
append(x, y, pos): Devuelve el vector que resulta de añadir
al vector x los elementos del vector y, a
continuación de la posición pos. El parámetro
pos es opcional y si no se indica, los
elementos de y se añaden al final de los de
x.
Eliminar/omitir elementos de un vector
Para eliminar los elementos que ocupan una determinada posición se
utiliza el operador de acceso, es decir, los corchetes [ ]
pero con los índices correspondientes a las posiciones a eliminar, en
negativo.
Eliminación de un vector Para eliminar los elementos de un vector
basta con asignar NULL a la variable que lo contiene, pero
si se quiere liberar la memoria que ocupa la variable se utiliza la
función rm().
Operaciones aritméticas con vectores
- Operaciones aritméticas elemento a elemento Para vectores numéricos las operaciones aritméticas habituales se aplican elemento a elemento. Si los vectores tienen distinto tamaño, el tamaño del vector más pequeño se equipara al tamaño del mayor, reutilizando sus elementos, empezando por el primero.
Producto escalar de vectores
Para calcular el producto escalar de dos vectores numéricos se
utiliza el operador %*%. Si los vectores tienen distinto
tamaño se produce un error.
Factores
- Operaciones con factores
Un factor es una estructura de datos especial que se utiliza para representar categorías de variables cualitativas y por tanto puede tomar un conjunto finito de valores predefinidos conocido como niveles del factor.
Para definir un factor se utiliza la siguiente función:
factor(x, levels = niveles): Crea un dato de tipo factor
con los elementos del vector x. Los niveles del factor
pueden indicarse mediante el parámetro levels, pasándole un
vector con los valores posibles. Si no se indica el parámetro
levels los niveles del factor se obtienen automáticamente a
partir de los elementos del vector x (tantos niveles con
valores distintos tenga).
Los factores son en realidad vectores de números enteros a los que se le añade un atributo especial para indicar los niveles del factor.
Para definir un factor se utiliza la siguiente función:
factor(x, levels = niveles): Crea un dato de tipo factor
con los elementos del vector x. Los niveles del factor
pueden indicarse mediante el parámetro levels, pasándole un
vector con los valores posibles. Si no se indica el parámetro
levels los niveles del factor se obtienen automáticamente a
partir de los elementos del vector x (tantos niveles con
valores distintos tenga).
Los factores son en realidad vectores de números enteros a los que se le añade un atributo especial para indicar los niveles del factor.
Es posible establecer un orden entre los niveles de un factor
añadiendo el parámetro ordered = TRUE a la función
anterior. Esto es útil para representar categorías ordinales entre las
que existe un orden natural.
is.factor(x): Devuelve el booleano TRUE si
x es del tipo factor, y FALSE en caso
contrario.
Se puede modificar los elementos de un factor de manera similar a
como se modifican los elementos de un vector, es decir accediendo al
elemento que se quiere modificar y asignándole un nuevo valor. La única
diferencia con los vectores es que si el nuevo valor que se quiere
asignar no está entre los niveles del factor, se obtiene el valor
NA.
Listas
Las listas son colecciones ordenadas de elementos que pueden ser de distintos tipos. Los elementos de una lista también pueden ser de tipos estructurados (vectores o listas), lo que las convierte en el tipo de dato más versátil de R. Como veremos más adelante, otras estructuras de datos como los data frames o los propios modelos estadísticos se construyen usando listas.
Creación de listas
Para construir una lista se utiliza la función
list():
list(x1, x2, ...): Devuelve la lista con los elementos
x1, x2, etc.
Al igual que con los vectores, es posible asignar un nombre a cada uno de los elementos de una lista.
list("nombre" = "María", "edad" = 21, "dirección" = list("calle" = "Delicias", "número" = 24, "municipio" = "Madrid"))## $nombre
## [1] "María"
##
## $edad
## [1] 21
##
## $dirección
## $dirección$calle
## [1] "Delicias"
##
## $dirección$número
## [1] 24
##
## $dirección$municipio
## [1] "Madrid"
El número de elementos de una lista es su tamaño y puede averiguarse con la siguiente función:
lenght(x): Devuelve el número de elementos de la lista
x.
Acceso a los elementos de una lista
Se accede a los elementos de una lista de forma similar a los vectores, mediante índices enteros, lógicos o de cadena, entre corchetes [ ].
Al igual que los vectores, los elementos de una lista están ordenados y se puede utilizar un índice entero para acceder a los elementos que ocupan una determinada posición.
Modificación de los elementos de una lista
Para modificar uno o varios elementos de una lista basta con acceder a esos elementos y reasignarles valores con el operador de asignación.
## $nombre
## [1] "María"
##
## $edad
## [1] 22
Añadir elementos a una lista
La forma más sencilla de añadir un elemento con nombre a una lista es
indicando el nombre con el operador $ y asignándole un
valor con el operador de asignación <-:
x$nombre <- y: Añade el
elemento y a la lista x con el nombre nombre.
El nuevo elemento se añade siempre al final de la lista.
Para añadir elementos sin nombre o en una posición determinada se
puede utilizar la función append():
append(x, y, pos): Devuelve la lista vector que resulta
de añadir a x los elementos de la lista y, a
continuación de la posición pos. El parámetro
pos es opcional y, si no se indica, los elementos de
y se añaden al final de los de x.
## $nombre
## [1] "María"
##
## $edad
## [1] 21
##
## $email
## [1] "maria@ceu.es"
## $nombre
## [1] "María"
##
## $edad
## [1] 21
##
## $sexo
## [1] "Mujer"
##
## $email
## [1] "maria@ceu.es"
Es posible convertir una lista en un vector con la siguiente función:
unlist(x): Devuelve el vector que resulta de aplanar
recursivamente la lista x y convertir todos los elementos
al mismo tipo mediante coerción de tipos.
Matrices
Una matriz es una estructura de datos bidimensional de elementos del mismo tipo organizados en filas y columnas. Una matriz es similar a un vector pero contiene una atributo adicional con sus dimensiones (número de filas y número de columnas).
Creación de matrices
Para crear una matriz se utiliza la siguiente función:
matrix(x, nrow = m, ncol = n): Devuelve la matriz con
los elementos del vector x organizados en n
filas y `mc columnas. Habitualmente basta con especificar el número de
filas o el número de columnas.
Como se puede observar en el ejemplo anterior, los elementos se
disponen por columnas, pero se pueden disponer los elementos por filas
pasando el parámetro byrow = TRUE a la función matrix.
Es posible poner nombres a las filas y a las columnas de una matriz añadiendo el parámetro dimnames y pasándole una lista de dos vectores de cadenas con los nombres de las filas y las columnas respectivamente.
Para obtener los nombres de las filas y las columnas de una matriz se utilizan las siguientes funciones:
rownames(x): Devuelve un vector de cadenas de caracteres con los nombres de las filas de la matrizx.
colnames(x): Devuelve un vector de cadenas de caracteres con los nombres de las columnas de la matrizx.
Para obtener el número de elementos y las dimensiones de una matriz se pueden utilizar las siguientes funciones:
length(x): Devuelve un entero con el número de elementos de la matrizx.nrow(x): Devuelve un entero con el número de filas de la matrizx.ncol(x): Devuelve un entero con el número de columnas de la matrizx.dim(x): Devuelve un vector de dos enteros con el número de filas y el número de columnas de la matrizx.
Usando esta última función se pueden modificar las dimensiones de una matriz asignando un vector de dos enteros con las nuevas dimensiones. Esto también permite crear una matriz a partir de un vector.
Acceso a los elementos de una matriz
Para acceder a los elementos de una matriz se utilizan dos índices
(uno para las filas y otro para las columnas), separados por comas y
entre corchetes [] a continuación de la matriz. Al igual
que para los vectores, los índices pueden ser enteros, lógicos o de
cadenas de caracteres.
Para acceder a los elementos de una matriz mediante índices enteros se indica el número de fila y el número de columna del elemento entre corchetes:
x[i,j]: Devuelve el elemento de la matriz x
que está en la fila i y la columna j. Se puede
acceder a más de un elemento indicando un vector de enteros para las
filas y otro para las columnas. De esta manera se obtiene una submatriz.
Si no se indica la fila o la columna se obtienen todos los elementos de
todas las filas o columnas. Al igual que para vectores, se pueden
utilizar enteros negativos para descartar filas o columnas.
Cuando se utilizan índices lógicos, se obtienen los elementos
correspondientes a las filas y columnas donde está el valor booleano
TRUE.
Si las filas y las columnas de una matriz tienen nombre, es posible acceder a sus elementos usando los nombres de las filas y columnas como índices.
Finalmente, es posible combinar distintos tipos de índices (enteros, lógicos o de cadena) para indicar las filas y las columnas a las que acceder.
Pertenencia a una matriz
Para comprobar si un valor en particular es un elemento de una matriz
se puede utilizar el operador %in%:
x %in% y: Devuelve el booleano TRUE si
x es un elemento de la matriz y, y
FALSE en caso contrario.
Modificación de los elementos de una matriz
Para modificar uno o varios elementos de una matriz basta con acceder a esos elementos y usar el operador de asignación para asignar nuevos valores.
Añadir elementos a una matriz
Para añadir nuevas filas o columnas a una matriz se utilizan las siguientes funciones:
rbind(x, y): Devuelve la matriz que resulta de añadir
nuevas filas a la matriz x con los elementos del vector
y. cbind(x, y): Devuelve la matriz que resulta
de añadir nuevas columnas a la matriz x con los elementos
del vector y.
Para trasponer una matriz se utiliza la función siguiente:
t(x): Devuelve la matriz traspuesta de la matrizx.
Operaciones aritméticas con matrices
Para matrices numéricas las operaciones aritméticas habituales se aplican elemento a elemento. Si las dimensiones de las matrices son distintas se produce un error.
Multiplicación de matrices
Para multiplicar dos matrices numéricas se utiliza el operador
%*%.
Determinante de una matriz
Para calcular el determinante de una matriz numérica cuadrada se utiliza la siguiente función:
det(x): Devuelve el determinante de la matriz
x. Si x no es una matriz numérica cuadrada
produce un error.
Inversa de una matriz
Para calcular la matriz inversa de una matriz numérica cuadrada se utiliza la siguiente función:
solve(x): Devuelve la matriz inversa de la matriz
x. Si x no es una matriz numérica cuadrada
produce un error. Si la matriz no es invertible por tener determinante
nulo también se obtiene un error.
Autovalores y autovectores de una matriz
Para calcular los autovalores y los autovectores de una matriz numérica cuadrada se utiliza la siguiente función:
eigen(x): Devuelve una lista con los autovalores y los
autovectores de la matriz x. Para acceder a los autovalores
se utiliza el nombre values y para acceder a los
autovectores se utiliza el nombre vectors. Si
x no es una matriz numérica cuadrada produce un error.
Data frames
Un data frame es una estructura bidimensional cuyos elementos se organizan por filas y columnas de manera similar a una matriz. La principal diferencia con las matrices es que sus columnas están formadas por vectores, pero pueden tener tipos de datos distintos. Un data frame es un caso particular de lista formada por vectores del mismo tamaño con nombre.
Los data frames son las estructuras de datos más utilizadas en R para almacenar los datos en los análisis estadísticos.
Para crear un data frame se utiliza la siguiente función:
data.frame(nombrex = x, nombrey = y, ...): Devuelve el
data frame con columnas los vectores x, y,
etc. y nombres de columna nombrex, nombrey,
etc.
Para grandes conjuntos de datos es más común crear un data frame a partir de un fichero en formato csv mediante la siguiente función:
read.csv(f): Devuelve el data frame que se genera a partir de los datos del fichero csvf. Cada fila del fichero csv se corresponde con una fila del data frame y por defecto utiliza la coma,parara separar los datos de las columnas y punto.como separador de decimales de los datos numéricos. Los nombres de las columnas se obtienen automáticamente a partir de la primera fila del fichero.
read.csv2(f): Funciona igual que la función anterior pero utiliza como separador de columnas el punto y coma;y como separador de decimales la coma,.
Coerción de otras estructuras de datos a data frames
Para convertir otras estructuras de datos en data frames, se utiliza la siguiente función:
as.data.frame(x): Devuelve el data frame que se obtiene
a partir la estructura de datos x a plicanco las siguientes
reglas de coerción: * Si x es un vector se obtiene un data
frame con una sola columna.
* Si x es una lista se obtiene un data frame con tantas
columnas como elementos tenga la lista. Si los elementos de la lista
tienen tamaños distintos se obtiene un error.
* Si x es una matriz se obtiene un data frame con el mismo
número de columnas y filas que la matriz.
Acceso a los elementos de un data frame
Puesto que un data frame es una lista, se puede acceder a sus
elementos como se accede a los elementos de una lista utilizando
índices. Con corchetes simples [ ] se obtiene siempre un
data frame, mientras que con corchetes dobles [[ ]] o
$ se obtiene un vector. Pero también se puede acceder a los
elementos de un data frame como si fuese una matriz, indicando un par de
índices para las filas y las columnas respectivamente.
Para acceder a las primeras o últimas filas de un data frame se pueden utilizar las siguientes funciones:
head(df, n): Devuelve un data frame con lasnprimeras filas del data framedf.
tail(df, n): Devuelve un data frame con lasnúltimas filas del data framedf.
Estas funciones son útiles para darse una idea del contenido de un data frame con muchas filas.
Para modificar uno o varios elementos de un data frame basta con acceder a esos elementos y usar el operador de asignación para asignar nuevos valores.
Añadir elementos a un data frame
Para añadir nuevas filas o columnas a una data frame se utilizan las mismas funciones que para matrices:
rbind(df, x): Devuelve el data frame que resulta de añadir nuevas filas al data framedfcon los elementos de la listax.
cbind(df, nombrex = x): Devuelve el data frame que resulta de añadir nuevas columnas al data framedfcon los elementos del vectorxcon nombrenombrex.
Para eliminar una columna de un data frame basta con acceder a la
columna y asignarle el valor NULL, mientras que para
eliminar una fila basta con acceder a la fila con índice negativo.
Funciones personalizadas
Una función es un bloque de código que tiene asociado un nombre, de manera que cada vez que se quiera ejecutar el bloque de código basta con invocar el nombre de la función. Las funciones permite dividir el código en unidades lógicas que resultan más fáciles de manejar y mantener.
En R las funciones son objetos en sí mimas y pueden usarse como
cualquier otro dato. El tipo de dato de las funciones es
function.
Parámetros y argumentos de una función
Una función puede recibir valores cuando se invoca a través de unas variables conocidas como parámetros que se definen entre paréntesis en la declaración de la función. En el cuerpo de la función se pueden usar estos parámetros como si fuesen variables.
Los valores que se pasan a la función en una llamada o invocación concreta de ella se conocen como argumentos y se asocian a los parámetros de la declaración de la función.
# Función con un parámetro
saludo <- function(nombre) {
print(paste("¡Hola ", nombre, "!", sep = ""))
}
# Llamada a la función con un argumento
saludo("Alf")## [1] "¡Hola Alf!"
En este ejemplo la función saludo tiene un parámetro
nombre. En la llamada a la función se pasa la cadena
Alf como argumento que se asocia al parámetro
nombre en el cuerpo de la función.
Los argumentos de una función pueden pasarse de dos formas:
Argumentos posicionales: Se asocian a los parámetros
de la función en el mismo orden que aparecen en la definición de la
función. Argumentos nominales : Se indica
explícitamente el nombre del parámetro al que se asocia un argumento de
la forma parametro = argumento. En este caso el orden de
los argumentos no importa.
Argumentos por defecto
En la definición de una función se puede asignar a cada parámetro un argumento por defecto, de manera que si se invoca la función sin proporcionar ningún argumento para ese parámetro, se utiliza el argumento por defecto.
Retorno de una función
Una función puede devolver un objeto de cualquier tipo tras su
invocación. Para ello se utiliza la función return(),
indicando entre paréntesis el valor que devuelve la función. El retorno
suele realizarse al final del cuerpo de la función, porque con él
finaliza la ejecución de la función y se devuelve el control de la
ejecución al punto desde donde se llamó a la función, de manera que
cualquier instrucción de cuerpo que vaya después no se ejecutará. Si no
se indica ningún objeto, la función devolverá el valor de la última
expresión calculada en el cuerpo de la función.
Entorno y ámbito de las variables
El entorno de un programa en R es el conjunto de todos los objetos
(funciones, variables, etc.) creados durante la ejecución del programa.
Cuando se ejecuta el interprete de R siempre se crea un primer entorno
R_GlobalEnv conocido como entorno global. Es posible
referirse a él en cualquier momento con la constante
.GlobalEnv.
Para ver el entorno activo en cada momento de la ejecución y el contenido del mismo se utiliza la siguiente función:
environment(): Devuelve el nombre del entorno actual.
ls(): Devuelve un vector con los nombres de las objetos
(variables, funciones, etc.) que contiene el entorno global.
Los parámetros y los objetos (funciones, variables, etc.) definidos dentro de una función son de ámbito local, mientras que los objetos definidos fuera de ella en alguno de los entornos ancestros son de ámbito global.
Tanto los parámetros como las variables del ámbito local de una función sólo están accesibles durante la ejecución de la función, es decir, cuando termina la ejecución de la función estas variables desaparecen y no son accesibles desde fuera de la función.
Cuando una función declara un objeto (función, variable, etc.) que ya existe en alguno de los entornos ancestros con ámbito global, durante la ejecución de la función el objeto global queda eclipsado por el local y no es accesible hasta que finaliza la ejecución de la función.
Las variables globales están accesibles siempre que no sean
eclipsadas por otras con el mismo nombre de ámbito local. Si embargo,
cuando se intenta asignar un valor a una variable global en el ámbito
local, se crea una nueva variable local. Para asignar valores a
variables globales en el ámbito local se tiene que utilizar el operador
de superasignación <<-. Cuando se utiliza este
operador para asignar un valor a una variable, R busca la variable
entorno padre, y si no existe continua con la búsqueda en los entornos
ancestros hasta llegar a entorno global. Si la búsqueda tiene éxito,
asigna el nuevo valor a la variable global, mientras que si no tiene
éxito se crea una nueva variable de ámbito local y se le asigna el
valor.
Componentes de una función
Los tres componentes de una función son:
Cuerpo: Es el código dentro de la función.Parámetros: Es la lista de parámetros que requiere la función.Entorno: Es donde se ubican las variables de la función.
Para acceder a estos componentes se pueden utilizar las siguientes funciones:
body(f): Devuelve el cuerpo de la funciónf.formals(f): Devuelve la lista de parámetros de la funciónf.environment(f): Devuelve el entorno de la funciónf.
Funciones recursivas
Una función recursiva es una función que en su cuerpo contiene una llama a sí misma.
La recursión es una práctica común en la mayoría de los lenguajes de programación ya que permite resolver las tareas recursivas de manera más natural.
Para garantizar el final de una función recursiva, las sucesivas llamadas tienen que reducir el grado de complejidad del problema, hasta que este pueda resolverse directamente sin necesidad de volver a llamar a la función. De lo contrario la recursión no tendría fin y nunca terminaría la ejecución de la función.
Paquetes (librerías)
Para facilitar la reutilización código y datos R permite la creación
de paquetes que pueden importarse desde otros programas. Un paquete es
una colección de código, funciones y datos que se almacenan en un
fichero dentro de un directorio llamado library en el
entorno de R. Para ver la ubicación de este directorio dentro del
sistema de archivos local se puede utilizar la función
.libPaths().
Durante la instalación de R también se instalan varios paquetes básicos que están disponibles en cualquier sesión de trabajo con R. Pero añadir nuevas funciones o procedimientos es necesario instalar el paquete que los contiene y después cargarlo en la sesión de trabajo.
Para ver los paquetes instalados en un ordenador se utiliza la
función library().
La mayor parte de los paquetes para R están disponibles en el repositorio oficial CRAN (Comprehensive R Archive Network), aunque cualquier persona puede desarrollar un paquete y ponerlo a disposición de la comunidad en cualquier otro repositorio.
Existen distintas formas de instalar un paquete en R:
- Directamente desde el repositorio oficial CRAN
- Desde otros repositorios no oficiales (por ejemplo Github)
- Descargando el paquete e instalándolo manualmente.
Para instalar un paquete desde el repositorio oficial CRAN se utiliza la siguiente función:
install.packages(x): Obtiene el paquete con el nombre
x desde un servidor con el repositorio CRAN y lo instala
localmente en el directorio library del entorno de R. Se
puede instalar más de un paquete a la vez pasando un vector con los
nombres de los paquetes.
El paquete remotes incorpora funciones para instalar
paquetes alojados en otros repositorios habituales para el desarrollo de
software como GitHub, GitLab, etc.
Finalmente es posible instalar un paquete manualmente a partir de su código fuente. Para ello hay previamente hay que descargar el código fuente del paquete en un fichero comprimido en formato zip y después utilizar la siguiente función:
install.packages(x, repos = NULL, type = "source"):
Instala el paquete ubicado en la ruta x del sistema de
archivos local en la librería library. Una vez instalado un paquete ya
está disponible para cargarlo en cualquier sesión de trabajo de R y no
es necesario volver a instalarlo.
Carga de un paquete
Una vez instalado un paquete, para poder ejecutar su contenido es necesario cargarlo en el entorno de trabajo de R. Para ello se utiliza la siguiente función:
library(x): Ejecuta el código del paquete x
en la sesión de trabajo activa.
Paquetes habituales
A continuación se presenta una lista ordenada alfabéticamente (no por importancia) de los paquetes más populares para el análisis de datos:
caretes un paquete para la creación de modelos de clasificación y regresión mediante aprendizaje automático.data.tablees un paquete para la manipulación de grandes conjuntos de datos (de hasta 100GB) de manera rápida y eficiente.devtoolses un paquete con herramientas para el desarrollo de paquetes en R.knitres un paquete que proporciona un motor para la generación de informes dinámicos que permite la integración de código en R con los lenguajes de procesamiento de textos LaTeX, HTML, Markdown, AsciiDoc o reStructuredText.mlr3es un paquete que proporciona funciones para las principales técnicas de aprendizaje automático.plotlyes un paquete para la creación de gráficos interactivos.rmarkdownes un paquete que facilita el uso del paqueteknitrpara la elaboración de documentos en múltiples formatos (HTML, pdf, Word y otros) permitiendo la integración de código R en el lenguaje Markdown.shinyes un paquete para la construcción de aplicaciones web interactivas.tidymodelses una colección de paquetes para la construcción y evalucación de modelos con técnicas de aprendizaje automático.tidyversees una colección de paquetes para la Ciencia de Datos que incluye paquetes para la carga, limpieza, manipulación y representación gráfica de datos.
Análisis de Datos Biomédicos
ggplot2: Para crear gráficos avanzados y personalizables en bioestadística.epiR: Paquete para realizar análisis epidemiológicos como tasas, razones de riesgo, odds ratios, etc.pROC: Útil para trabajar con curvas ROC y evaluar modelos predictivos.Metaymetafor: Para realizar metaanálisis.gtsummary: Genera tablas resumen para análisis descriptivos y modelos estadísticos.
Bioinformática y Genómica (relacionado con bioestadística)
DESeq2: Análisis de datos de expresión génica (RNA-seq).edgeR: Para datos de conteo de secuenciación y análisis diferencial.GenABEL: Análisis estadístico genético.Bioconductor: Repositorio con cientos de paquetes útiles para análisis bioinformáticos.
Preprocesamiento de datos
Cualquier análisis de datos comienza con la carga de datos en un data frame. Normalmente los datos brutos deben limpiarse y prepararse para su análisis. Este proceso se conoce como preprocesamiento de datos y suele incluir las siguientes tareas:
- Reestructuración del data frame.
- Selección de las variables (columnas) de interés.
- Filtrado de los casos (filas) de interés.
- Cálculo de nuevas variables a partir de las existentes.
- Ordenación de datos.
- Agrupación de datos.
- Tratamiento de datos no disponibles (
NA,NaN).
Estas tareas pueden realizarse con las funciones básicas de R pero
actualmente existen paquetes que facilitan mucho su realización como por
ejemplo la colección de paquetes tidyverse.
Tibbles
El paquete tibble define la estructura de datos tibble
que es similiar a los data frames, pero optimizada, ya que realiza una
carga en memoria y evaluación perezosa, lo que hace más eficiente el
manejo de grandes volúmenes de datos estructurados en forma de tabla.
Los tibbles, además, suelen dar más información sobre el contenido y la
estructura de los datos, así como de incoherencias en los datos.
Los tibbles nunca cambian el tipo de los datos (por ejemplo de cadenas a factores), nunca cambian los nombres de las variables, ni crean nombres de filas, como suelen hacer los data frames.
Aunque los paquetes de tidyverse trabajan perfectamente
con data frames, están optimizados para trabajar con tibbles.
Para convertir un data frame en un tibble se utiliza la función
as_tibble(df): Convierte el data framedfen un tibble.
library(tibble)
df <- data.frame(asignatura = c("Matemáticas", "Física", "Economía"), nota = c(8.5, 7, 4.5))
as_tibble(df)## # A tibble: 3 × 2
## asignatura nota
## <chr> <dbl>
## 1 Matemáticas 8.5
## 2 Física 7
## 3 Economía 4.5
Al igual que los data frames, las columnas de los tibbles son vectores cuyos elementos son del mismo tipo, de manera que suelen representar variables en los estudios estadísticos, mientras que las filas representan individuos, aunque no siempre es así.
El paquete dplyr
El paquete dplyr proporciona una gramática para el
preprocesamiento de data frames o tibbles, de manera que cada acción
sobre data frame se corresponde con un verbo y las funciones que
realizan esa acción tienen como nombre el verbo correspondiente. Las
funciones de preprocesamiento más habituales incluidas en el paquete
dplyr son:
count: Cuenta el número de observaciones de un data frame.select: Selecciona un subconjunto de columnas de un data frame.filter: Selecciona un subconjunto de filas de un data frame.arrange: Reordena las filas de un data frame.rename: Renombra las columnas de un data frame.mutate: Añade nuevas columnas a un data frame o transforma las existentes.summarise: Genera resúmenes estadísticos de las columnas de un data frame.group_by: Divide las filas de un data frame en grupos de acuerdo a una columna categórica.