Un vector es una secuencia ordenada de datos. R
dispone de muchos tipos de datos, por ejemplo:
logical
: lógicos (TRUE
o FALSE
)integer
: números enteros, \(\mathbb Z\)numeric
: números reales, \(\mathbb R\)complex
: números complejos, \(\mathbb C\)character
: palabrasEn los vectores de R
, todos sus objetos han de ser del mismo tipo: todos números, todos palabras, etc. Cuando queramos usar vectores formados por objetos de diferentes tipos, tendremos que usar listas generalizadas, lists
que veremos al final del tema.
c()
: para definir un vectorscan()
: para definir un vectorfix(x)
: para modificar visualmente el vector \(x\)rep(a,n)
: para definir un vector constante que contiene el dato \(a\) repetido \(n\) vecesc(1,2,3)
[1] 1 2 3
rep("Mates",7)
[1] "Mates" "Mates" "Mates" "Mates" "Mates" "Mates" "Mates"
Una progresión aritmética es una sucesión de números tales que la diferencia, \(d\), de cualquier par de términos sucesivos de la secuencia es constante. \[a_n = a_1 + (n-1)\cdot d\]
seq(a,b,by=d)
: para generar una progresión aritmética de diferencia \(d\) que empieza en \(a\) hasta llegar a \(b\)seq(a,b, length.out=n)
: define progresión aritmética de longitud \(n\) que va de \(a\) a \(b\) con diferencia \(d\). Por tanto \(d=(b-a)/(n-1)\)seq(a,by=d, length.out=n)
: define la progresión aritmética de longitud \(n\) y diferencia \(d\) que empieza en \(a\)a:b
: define la secuencia de números enteros (\(\mathbb{Z}\)) consecutivos entre dos números \(a\) y \(b\)Cuando queremos aplicar una función a cada uno de los elementos de un vector de datos, la función sapply
nos ahorra tener que programar con bucles en R
:
sapply(nombre_de_vector,FUN=nombre_de_función)
: para aplicar dicha función a todos los elementos del vectorsqrt(x)
: calcula un nuevo vector con las raíces cuadradas de cada uno de los elementos del vector \(x\)Dado un vector de datos \(x\) podemos calcular muchas medidas estadísticas acerca del mismo:
length(x)
: calcula la longitud del vector \(x\)max(x)
: calcula el máximo del vector \(x\)min(x)
: calcula el mínimo del vector \(x\)sum(x)
: calcula la suma de las entradas del vector \(x\)prod(x)
: calcula el producto de las entradas del vector \(x\)mean(x)
: calcula la media aritmética de las entradas del vector \(x\)diff(x)
: calcula el vector formado por las diferencias sucesivas entre entradas del vector original \(x\)cumsum(x)
: calcula el vector formado por las sumas acumuladas de las entradas del vector original \(x\)
cumsum(x)
es la suma de las entradas de \(x\) hasta su posicióncuadrado = function(x){x^2}
v = c(1,2,3,4,5,6)
sapply(v, FUN = cuadrado)
[1] 1 4 9 16 25 36
mean(v)
[1] 3.5
cumsum(v)
[1] 1 3 6 10 15 21
sort(x)
: ordena el vector en orden natural de los objetos que lo forman: el orden numérico creciente, orden alfabético…rev(x)
: invierte el orden de los elementos del vector \(x\)v = c(1,7,5,2,4,6,3)
sort(v)
[1] 1 2 3 4 5 6 7
rev(v)
[1] 3 6 4 2 5 7 1
vector[i]
: da la \(i\)-ésima entrada del vector
vector[length(vector)]
: nos da la última entrada del vectorvector[a:b]
: si \(a\) y \(b\) son dos números naturales, nos da el subvector con las entradas del vector original que van de la posición \(a\)-ésima hasta la \(b\)-ésima.vector[-i]
: si \(i\) es un número, este subvector está formado por todas las entradas del vector original menos la entrada \(i\)-ésima. Si \(i\) resulta ser un vector, entonces es un vector de índices y crea un nuevo vector con las entradas del vector original,cuyos índices pertenecen a \(i\)vector[-x]
: si \(x\) es un vector (de índices), entonces este es el complementario de vector[\(x\)]También podemos utilizar operadores lógicos:
==
: =!=
: \(\neq\)>=
: \(\ge\)<=
: \(\le\)<
: \(<\)>
: \(>\)!
: NO lógico&
: Y lógico|
: O lógicov = c(14,5,6,19,32,0,8)
v[2]
[1] 5
v[-c(3,5)]
[1] 14 5 19 0 8
v[v != 19 & v>15]
[1] 32
which(x cumple condición)
: para obtener los índices de las entradas del vector \(x\) que satisfacen la condición dadawhich.min(x)
: nos da la primera posición en la que el vector \(x\) toma su valor mínimowhich(x==min(x))
: da todas las posiciones en las que el vector \(x\) toma sus valores mínimoswhich.max(x)
: nos da la primera posición en la que el vector \(x\) toma su valor máximowhich(x==max(x))
: da todas las posiciones en las que el vector \(x\) toma sus valores máximosFactor: es como un vector, pero con una estructura interna más rica que permite usarlo para clasificar observaciones
levels
: atributo del factor. Cada elemento del factor es igual a un nivel. Los niveles clasifican las entradas del factor. Se ordenan por orden alfabéticofactor()
o as.factor()
.factor(vector,levels=...)
: define un factor a partir del vector y dispone de algunos parámetros que permiten modificar el factor que se crea:
levels
: permite especificar los niveles e incluso añadir niveles que no aparecen en el vectorlabels
: permite cambiar los nombres de los niveleslevels(factor)
: para obtener los niveles del factor
Factor ordenado. Es un factor donde los niveles siguen un orden
ordered(vector,levels=...)
: función que define un factor ordenado y tiene los mismos parámetros que factorfac = factor(c(1,1,1,2,2,3,2,4,1,3,3,4,2,3,4,4),
levels = c(1,2,3,4), labels = c("Sus","Apr","Not","Exc"))
fac
[1] Sus Sus Sus Apr Apr Not Apr Exc Sus Not Not Exc Apr Not Exc Exc
Levels: Sus Apr Not Exc
facOrd = ordered(c(1,1,1,2,2,3,2,4,1,3,3,4,2,3,4,4),
levels = c(1,2,3,4), labels = c("Sus","Apr","Not","Exc"))
facOrd
[1] Sus Sus Sus Apr Apr Not Apr Exc Sus Not Not Exc Apr Not Exc Exc
Levels: Sus < Apr < Not < Exc
List. Lista formada por diferentes objetos, no necesariamente del mismo tipo, cada cual con un nombre interno
list(...)
: función que crea una list
list$componente
list[[i]]
. Lo que obtendremos es una list formada por esa única componente, no el objeto que forma la componentestr(list)
: para conocer la estructura interna de una listnames(list)
: para saber los nombres de la listx = c(1,-2,3,4,-5,6,7,-8,-9,0)
miLista = list(nombre = "X", vector = x, media = mean(x), sumas = cumsum(x))
miLista
$nombre
[1] "X"
$vector
[1] 1 -2 3 4 -5 6 7 -8 -9 0
$media
[1] -0.3
$sumas
[1] 1 -1 2 6 1 7 14 6 -3 -3
Entender las estructura de una lista y sus nombres:
str(miLista)
List of 4
$ nombre: chr "X"
$ vector: num [1:10] 1 -2 3 4 -5 6 7 -8 -9 0
$ media : num -0.3
$ sumas : num [1:10] 1 -1 2 6 1 7 14 6 -3 -3
names(miLista)
[1] "nombre" "vector" "media" "sumas"
matrix(vector, nrow=n, byrow=valor_lógico)
: para definir una matriz de \(n\) filas formada por las entradas del vector
nrow
: número de filasbyrow
: si se iguala a TRUE, la matriz se construye por filas; si se iguala a FALSE (valor por defecto), se construye por columnas. -ncol
: número de columnas (puede usarse en lugar de nrow)rbind(vector1, vector2, ...)
: construye la matriz de filas vector1, vector2,…cbind(vector1, vector2, ...)
: construye la matriz de columnas vector1, vector2,…
diag(vector)
: para construir una matriz diagonal con un vector dado
matriz[i,j]
: indica la entrada (\(i,j\)) de la matriz, siendo \(i,j\in\mathbb{N}\). Si \(i\) y \(j\) son vectores de índices, estaremos definiendo la submatriz con las filas pertenecientes al vector \(i\) y columnas pertenecientes al vector \(j\)matriz[i,]
: indica la fila \(i\)-ésima de la matriz, siendo \(i\in\mathbb{N}\)matriz[,j]
: indica la columna \(j\)-ésima de la siendo \(j\in\mathbb{N}\)
diag(matriz)
: para obtener la diagonal de la matriznrow(matriz)
: nos devuelve el número de filas de la matrizncol(matriz)
: nos devuelve el número de columnas de la matrizdim(matriz)
: nos devuelve las dimensiones de la matrizsum(matriz)
: obtenemos la suma de todas las entradas de la matrizprod(matriz)
: obtenemos el producto de todas las entradas de la matrizmean(matriz)
: obtenemos la media aritmética de todas las entradas de la matrizcolSums(matriz)
: obtenemos las sumas por columnas de la matrizrowSums(matriz)
: obtenemos las sumas por filas de la matrizcolMeans(matriz)
: obtenemos las medias aritméticas por columnas de la matrizrowMeans(matriz)
: obtenemos las medias aritméticas por filas de la matrizapply(matriz, MARGIN=..., FUN=función)
: para aplicar otras funciones a las filas o las columnas de una matriz
MARGIN
: ha de ser 1 si queremos aplicar la función por filas; 2 si queremos aplicarla por columnas; o c(1,2) si la queremos aplicar a cada entradaA = matrix(c(1,2,3,4,5,6,7,8,9), ncol = 3)
apply(A, MARGIN = c(1,2), FUN = cuadrado)
[,1] [,2] [,3]
[1,] 1 16 49
[2,] 4 25 64
[3,] 9 36 81
apply(A, MARGIN = 1, FUN = sum)
[1] 12 15 18
apply(A, MARGIN = 2, FUN = sum)
[1] 6 15 24
t(matriz)
: para obtener la transpuesta de la matriz+
: para sumar matrices*
: para el producto de un escalar por una matriz%*%
: para multiplicar matricesmtx.exp(matriz,n)
: para elevar la matriz a \(n\)
Biodem
%%
: para elevar matrices
expm
det(matriz)
: para calcular el determinante de la matrizqr(matriz)$rank
: para calcular el rango de la matrizsolve(matriz)
: para calcular la inversa de una matriz invertible
solve(matriz,b)
, donde \(b\) es el vector de términos independienteseigen(matriz)
: para calcular los valores (vaps) y vectores propios (veps)
eigen(matriz)$values
: nos da el vector con los vaps de la matriz en orden decreciente de su valor absoluto y repetidos tantas veces como su multiplicidad algebraica.eigen(matriz)$vectors
: nos da una matriz cuyas columnas son los veps de la matriz.M = rbind(c(2,6,-8), c(0,6,-3), c(0,2,1))
eigen(M)
eigen() decomposition
$values
[1] 4 3 2
$vectors
[,1] [,2] [,3]
[1,] 0.2672612 -0.8164966 1
[2,] 0.8017837 0.4082483 0
[3,] 0.5345225 0.4082483 0
Si hay algún vap con multiplicidad algebraica mayor que 1 (es decir, que aparece más de una vez), la función eigen()
da tantos valores de este vap como su multiplicidad algebraica indica. Además, en este caso, R intenta que los veps asociados a cada uno de estos vaps sean linealmente independientes. Por tanto, cuando como resultado obtenemos veps repetidos asociados a un vap de multiplicidad algebraica mayor que 1, es porque para este vap no existen tantos veps linealmente independientes como su multiplicidad algebraica y, por consiguiente, la matriz no es diagonalizable.
M = matrix(c(0,1,0,-7,3,-1,16,-3,4), nrow=3, byrow=TRUE)
eigen(M)
eigen() decomposition
$values
[1] 3 2 2
$vectors
[,1] [,2] [,3]
[1,] -0.1301889 -0.1825742 -0.1825742
[2,] -0.3905667 -0.3651484 -0.3651484
[3,] 0.9113224 0.9128709 0.9128709
Consideramos que hay tres grandes grupos con diferentes formatos para organizar los datos:
3 Strucutred
No existen metadatos para saber que información contiene cada columna. Problema entre sistemas operativas entienden estos ficheros de forma distinta, y esto causa muchos problemas
Todos los campos estan separados por comas. Difícil interpretación si no tenemos toda la información, deben estar muy bien documentados. Hay mucha importáncia en la estructura de los datos (situación de las comas).
Muy utilizado para le intercanvio de datos, ya que estan parcialmente estructurados. Es un estándard público regulado, muy útil para el scrapping de webs.
Data frame. Un data frame es una tabla de doble entrada, formada por variables en las columnas y observaciones de estas variables en las filas, de manera que cada fila contiene los valores de las variables para un mismo caso o un mismo individuo.
data()
: para abrir una ventana con la lista de los objetos de datos a los que tenemos acceso en la sesión actual de R (los que lleva la instalación básica de R y los que aportan los paquetes que tengamos cargados.
data(package=.packages(all.available = TRUE))
obtendremos la lista de todos los objetos de datos a los que tenemos acceso, incluyendo los de los paquetes que tengamos instalados, pero que no estén cargados en la sesión actual.head(d.f,n)
: para mostrar las \(n\) primeras filas del data frame. Por defecto se muestran las 6 primeras filastail(d.f,n)
: para mostrar las \(n\) últimas filas del data frame. Por defecto semuestran las 6 últimasstr(d.f)
: para conocer la estructura global de un data framenames(d.f)
: para producir un vector con los nombres de las columnasstr(Orange)
Classes 'nfnGroupedData', 'nfGroupedData', 'groupedData' and 'data.frame': 35 obs. of 3 variables:
$ Tree : Ord.factor w/ 5 levels "3"<"1"<"5"<"2"<..: 2 2 2 2 2 2 2 4 4 4 ...
$ age : num 118 484 664 1004 1231 ...
$ circumference: num 30 58 87 115 120 142 145 33 69 111 ...
- attr(*, "formula")=Class 'formula' language circumference ~ age | Tree
.. ..- attr(*, ".Environment")=<environment: R_EmptyEnv>
- attr(*, "labels")=List of 2
..$ x: chr "Time since December 31, 1968"
..$ y: chr "Trunk circumference"
- attr(*, "units")=List of 2
..$ x: chr "(days)"
..$ y: chr "(mm)"
Mirando los primeros valores y los últimos:
head(Orange,4)
Tree age circumference
1 1 118 30
2 1 484 58
3 1 664 87
4 1 1004 115
tail(Orange,4)
Tree age circumference
32 5 1004 125
33 5 1231 142
34 5 1372 174
35 5 1582 177
rownames(d.f)
: para producir un vector con los identificadores de las filas
colnames(d.f)
: para producir un vector con los identificadores de las columnasdimnames(d.f)
: para producir una list formada por dos vectores (el de los identificadores de las filas y el de los nombres de las columnas)nrow(d.f)
: para consultar el número de filas de un data framencol(d.f)
: para consultar el número de columnas de un data framedim(d.f)
: para producir un vector con el número de filas y el de columnasd.f$nombre_variable
: para obtener una columna concreta de un dataframe
d.f[n,m]
: para extraer “trozos” del data frame por filas y columnas (funciona exactamente igual que en matrices) donde \(n\) y \(m\) pueden definirse como:
dataOrange = Orange
dataOrange[c(10:12),]
Tree age circumference
10 2 664 111
11 2 1004 156
12 2 1231 172
dataOrange[c(2,17),c(1,3)]
Tree circumference
2 1 58
17 3 75
dataOrange[2,3]
[1] 58
dataOrange[dataOrange$circumference<=50,]
Tree age circumference
1 1 118 30
8 2 118 33
15 3 118 30
22 4 118 32
29 5 118 30
30 5 484 49
read.table()
: para definir un data frame a partir de una tabla de datos contenida en un fichero
Aquí tenéis una lista de data frames para practicar
header = TRUE
: para indicar si la tabla que importamos tiene una primera fila con los nombres de las columnas. El valor por defecto es FALSEcol.names = c(...)
: para especificar el nombre de las columnas. No olvidéis que cada nombre debe ir entre comillassep
: para especificar las separaciones entre columnas en el fichero (si no es un espacio en blanco). Si es así, hay que introducir el parámetro pertinente entre comillasdec
: para especificar el signo que separa la parte entera de la decimal (si no es un punto. Si es así, hay que introducir el parámetro pertinente entre comillasstudents = read.table("http://www.public.iastate.edu/~maitra/stat501/datasets/morel.dat",
col.names = c("technicalDisciplines","aptitude","maths", "language",
"generalKnowledge"))
head(students,8)
technicalDisciplines aptitude maths language generalKnowledge
1 1 23 50 59 10
2 1 70 30 79 18
3 1 25 50 86 22
4 1 0 40 67 16
5 1 0 25 70 20
6 1 20 60 78 22
7 1 97 65 75 22
8 1 1 45 61 22
Otros parámetros relevantes:
stringsAsFactors
: para prohibir la transformación de las columnas de palabras en factores debemos usar stringsAsFactors=FALSE
(ya que por defecto, R realiza dicha transformación)
Para importar un fichero de una página web segura (cuyo url empiece con https), no podemos entrar directamente la dirección en read.table()
; una solución es instalar y cargar el paquete RCurl y entonces usar la instrucción read.table (textConnection(getURL(“url ”)),...)
.
read.csv()
: para importar ficheros en formato CSVread.xls()
o read.xlsx()
: para importar hojas de cálculo tipo Excel u OpenOffice en formato XLS o XLSX, respectivamente. Se necesita el paquete xlsxread.mtb()
: para importar tablas de datos Minitab. Se necesita el paquete foreignread.spss()
: para importar tablas de datos SPSS. Se necesita el paquete foreignwrite.table(df, file = "")
: para exportar un data frame a un fichero
file = ""
: es donde indicaremos el nombre que queremos darle al ficherosep
para indicar el símbolo de separación de columnas. Siempre entre comillasdec
para indicar la separación entre la parte entera y decimal de los datoswrite.table(students, file = "../data/StudentsData", dec = ".")
students2 = read.table("../data/StudentsData", header = TRUE)
str(students2)
'data.frame': 82 obs. of 5 variables:
$ technicalDisciplines: int 1 1 1 1 1 1 1 1 1 1 ...
$ aptitude : int 23 70 25 0 0 20 97 1 30 23 ...
$ maths : int 50 30 50 40 25 60 65 45 45 40 ...
$ language : int 59 79 86 67 70 78 75 61 65 64 ...
$ generalKnowledge : int 10 18 22 16 20 22 22 22 16 18 ...
data.frame(vector_1,...,vector_n)
: para construir un data frame a partir de vectores introducidos en el orden en el que queremos disponer las columnas de la tabla
data.frame
entrando una construcción de la forma nombre_variable = vector
rownames
: para especificar los identificadores de las filasstringsAsFactors
para evitar la transformación de las columnas de tipo palabra en factoresAlgebra = c(1,2,0,5,4,6,7,5,5,8)
Analysis = c(3,3,2,7,9,5,6,8,5,6)
Statistics = c(4,5,4,8,8,9,6,7,9,10)
grades = data.frame(Alg = Algebra, An = Analysis, Stat = Statistics)
str(grades)
'data.frame': 10 obs. of 3 variables:
$ Alg : num 1 2 0 5 4 6 7 5 5 8
$ An : num 3 3 2 7 9 5 6 8 5 6
$ Stat: num 4 5 4 8 8 9 6 7 9 10
fix(d.f)
: para crear / editar un data frame con el editor de datosnames(d.f)
: para cambiar los nombres de las variablesrownames(d.f)
: para modificar los identificadores de las filas. Han de ser todos diferentesdimnames(d.f)=list(vec_nom_fil, vec_nom_col)
: para modificar el nombre de las filas y de las columnas simultáneamented.f[núm_fila,] = c(...)
: para añadir una fila a un data frame
rbind()
para concatenar el data frame con la nueva filaCalculus = c(5,4,6,2,1,0,7,8,9,6)
grades2 = cbind(grades, Calculus)
head(grades2)
Alg An Stat Calculus
1 1 3 4 5
2 2 3 5 4
3 0 2 4 6
4 5 7 8 2
5 4 9 8 1
6 6 5 9 0
d.f$new_var
: para añadir una nueva variable al data frame
cbind()
. De este modo se puede añadir la columna directamente sin necesidad de convertirla antes a data frameas.character
: para transformar todos los datos de un objeto en palabrasas.integer
: para transformar todos los datos de un objeto a números enterosas.numeric
: para transformar todos los datos de un objeto a números realesdroplevels(d.f)
: para borrar los niveles sobrantes de todos los factores, ya que las columnas que son factores heredan en los sub-data frames todos los niveles del factor original, aunque no aparezcan en el trozo que hemos extraído
select(d.f, parámetros)
: para especificar que queremos extraer de un data frame
starts_with("x")
: extrae del data frame las variables cuyo nombre empieza con la palabra “x”ends_with("x")
: extrae del data frame las variables cuyo nombre termina con la palabra “x”contains("x")
: extrae del data frame las variables cuyo nombre contiene la palabra “x”dplyr
o mejor aún tidyverse
subset(d.f,condición,select = columnas)
: para extraer del data frame las filas que cumplen la condición y las columnas especificadas
select
sapply(d.f, función)
: para aplicar una función a todas las columnas de un data frame en un solo paso
na.rm=TRUE
: para evitar que el valor que devuelva la función para las columnas que contengan algún NA sea NAaggregate(variables~factors,data=d.f,FUN=función)
: para aplicar una función a variables de un data frame clasificadas por los niveles de un, o más de un, factor
cbind
attach(d.f)
: para hacer que R entienda sus variables como globales y que las podamos usar por su nombre, sin necesidad de añadir delante el nombre del data frame y el símbolo $
attach
, hubiéramos obtenido un mensaje de error al ejecutar esta función y no se hubiera reescrito la variable global originaldetach(d.f)
: para devolver la situación original, eliminando del entorno global las variables del data frame