pre code { color: #00008B; /* Azul oscuro */ }
Esta sección te permite conocer qué utilidades tiene R. A modo de resumen, podemos utilizar R como una calculadora para operaciones aritméticas y funciones matemáticas o podemos querer ir más allá y aprender el lenguaje R. Esta última opción es sin dudas la más interesante, por ello, primero te enseñaremos las reglas básicas de sintaxis para que puedas elaborar tus propios códigos y luego ahondaremos en los pilares de R: los objetos.
Operaciones Básicas
Operadores de cálculo: El listado de las funciones aritméticas básicas disponibles en R.
Entonces, si queremos utilizar R para cálculos matemáticos simples, basta con escribir:
# operaciones aritméticas básicas
2 + 3 # suma
## [1] 5
2 - 3 # resta
## [1] -1
2*3 # multiplicación
## [1] 6
2/3 # división
## [1] 0.6666667
2^3 # potenciación
## [1] 8
Hay que tener en cuenta que R utiliza la precedencia en las operaciones, esto quiere decir que primero se realizan las funciones exponenciales, luego la multiplicación y división según el orden de los operadores que hayan (paréntesis) y finalmente las sumas y restas también en el orden en el que estén presentes. Aquí tienen algunos ejemplos:
#conviene utilizar paréntesis
4^2 - 3*2
## [1] 10
(4^2) - (3*2)
## [1] 10
1 - 6 + 4
## [1] -1
(1 - 6) + 4
## [1] -1
2^-3
## [1] 0.125
2^(-3)
## [1] 0.125
Si queremos realizar cálculos con vectores, lo primero es construir los vectores (en este caso x e y) y luego aplicar las herramientas aritméticas.
v<-1:3
w<-2:4
+ v
## [1] 1 2 3
- w
## [1] -2 -3 -4
v + w
## [1] 3 5 7
v - w
## [1] -1 -1 -1
v * w
## [1] 2 6 12
v / w
## [1] 0.5000000 0.6666667 0.7500000
v ^ w
## [1] 1 8 81
v ** w
## [1] 1 8 81
v %% w
## [1] 1 2 3
v %/% w
## [1] 0 0 0
Operadores matemáticos: Por supuesto también podemos utilizar funciones matemáticas o estadísticas.
El vector de datos: Sea \(x\) un vector genérico y sea \(pp\) en este caso la etiqueta específica usada para \(x\) de modo que represente la precipitación:
pp=c(20,25,28,25,24,20,25,35,36,34,35,32,25,30,24,25,28,15,0,20,25,0,32) #vector de precipitación
max(pp) #máximo valor de pp
## [1] 36
min(pp) #mínimo valor de pp
## [1] 0
range(pp) #rango de valores de pp
## [1] 0 36
sum(pp) #suma de todos los datos de pp
## [1] 563
mean(pp) #media de pp
## [1] 24.47826
median(pp) #mediana de la pp
## [1] 25
diff(pp) #vector de diferencias sucesivas de pp
## [1] 5 3 -3 -1 -4 5 10 1 -2 1 -3 -7 5 -6 1 3 -13 -15 20
## [20] 5 -25 32
prod(pp) #productoria de tolos los valores de pp
## [1] 0
cumsum(pp) #pp acumulada
## [1] 20 45 73 98 122 142 167 202 238 272 307 339 364 394 418 443 471 486 486
## [20] 506 531 531 563
var(pp) #varianza de la pp
## [1] 89.26087
sqrt(pp) #raiz cuadrada de los valores de pp
## [1] 4.472136 5.000000 5.291503 5.000000 4.898979 4.472136 5.000000 5.916080
## [9] 6.000000 5.830952 5.916080 5.656854 5.000000 5.477226 4.898979 5.000000
## [17] 5.291503 3.872983 0.000000 4.472136 5.000000 0.000000 5.656854
sd(pp) #desviación estándar de la pp
## [1] 9.447797
quantile(pp,0.25) # cuartil inferior y superior de la pp
## 25%
## 22
quantile(pp,0.25) # cuartil inferior y superior de la pp
## 25%
## 22
length(pp) # número de datos en el vector de pp
## [1] 23
Operadores Lógicos: Los operadores lógicos en R se utilizan para realizar operaciones lógicas en los valores de las variables. El resultado de estas operaciones es un valor lógico, es decir, verdadero o falso. Aquí tienes una lista de los principales operadores lógicos en R
En ocasiones combinamos algunas funciones con operadores lógicos, tales como:
any(pp<30) #al menos un valor es menor a 30
## [1] TRUE
all(pp>10) #Son todos los valores de pp mayores a 10
## [1] FALSE
which(pp==25) #posiciones donde la precipitación vale 25
## [1] 2 4 7 13 16 21
Cuidado con la notación científica
R decide automáticamente cuando utilizar notación científica. Los siguientes ejemplos enseñan cómo se representan números muy pequeños o muy grandes. Si utilizamos notación científica, el número 0,000182 se debe escribir como \(1,82\times10^{−4}\), y en R se escribe \(1.82e{-4}\). A su vez, el número 11000, se escribe en notación científica \(1,10\times^4\), y en R se escribe \(1.00e4\).
Nota: No es lo mismo \(1.82e{-4}\) que \(1.82e^{-4}\)
Cuidado con la notación científica
Si queremos especificar el número de cifras significativas que queremos observar, basta con escribir:
signif(0.1723,digits=2)
## [1] 0.17
Recordemos que los ceros a la izquierda del punto no son cifras significativas.
Redondeo
También tenemos la posibilidad de redondear una cifra, solo tenemos que especificar el número de cifras (o dígitos) que queremos obtener. Por ejemplo:
round(1.12345,digits=2)
## [1] 1.12
(Casi) todo en R es un objeto, ¡pero existen distintos tipos de objetos!.
Vectores
Un vector es una colección ordenada de elementos del mismo tipo. Podemos crear un vector de distintas maneras. Por ejemplo, utilizando el operador de concatenación \(c\):
v1<-c(1,2,3);v1 #números
## [1] 1 2 3
v2<-c(T,T,F,T,T,T,F);v2 #lógico
## [1] TRUE TRUE FALSE TRUE TRUE TRUE FALSE
v3<-c("A","T","G","G","T","T","G","A","A","A","A","A","T","T","G","G","G","C","C","G","A","T");v3 #Caracteres
## [1] "A" "T" "G" "G" "T" "T" "G" "A" "A" "A" "A" "A" "T" "T" "G" "G" "G" "C" "C"
## [20] "G" "A" "T"
Podemos averiguar si el objeto es un vector
is.vector(v3)
## [1] TRUE
Matrices
Son generalizaciones multidimensionales del vector, con elementos del mismo tipo. Es decir, están formados por varias columnas (o filas) de vectores. Para crear una matriz en R solo tienes que utilizar la función matrix() con los valores que queramos agregar y el número de columnas o filas que queremos generar. Además puedes especificar cómo quieres que se rellene la matriz, si con los valores agregados por filas o columnas.
M1<-matrix(1:9,nrow=3);M1 #ordena por columnas por defecto
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
M2<-matrix(1:9,nrow=3, byrow = T);M2 #ordena por filas
## [,1] [,2] [,3]
## [1,] 1 2 3
## [2,] 4 5 6
## [3,] 7 8 9
Las funciones rownames() y colnames() nos permiten agregarles nombres a las filas y columnas, respectivamente.
rownames(M1)=paste0("fila",1:3)
colnames(M2)=paste0("columna",1:3)
M1;M2
## [,1] [,2] [,3]
## fila1 1 4 7
## fila2 2 5 8
## fila3 3 6 9
## columna1 columna2 columna3
## [1,] 1 2 3
## [2,] 4 5 6
## [3,] 7 8 9
Nota: Observa lo que hace la función paste0(): mantiene el texto fila o columna y los pega en la secuencia de números especificada.
A continuación puedes observar un listado de operaciones que podemos realizar con las matrices.
Arreglos
También son generalizaciones multidimensionales del vector, con elementos de un solo tipo. Un vector tiene una dimensión(o ninguna según R), una matriz tiene dos dimensiones, y un arreglo tiene dos o más dimensiones.
(a<-array(1:24, dim=c(2,3,4))) # dos filas 3 columnas y 4 capas
## , , 1
##
## [,1] [,2] [,3]
## [1,] 1 3 5
## [2,] 2 4 6
##
## , , 2
##
## [,1] [,2] [,3]
## [1,] 7 9 11
## [2,] 8 10 12
##
## , , 3
##
## [,1] [,2] [,3]
## [1,] 13 15 17
## [2,] 14 16 18
##
## , , 4
##
## [,1] [,2] [,3]
## [1,] 19 21 23
## [2,] 20 22 24
Nota: Observa que cuando toda la línea de código se coloca entre paréntesis se imprime su ejecución sin necesidad de llamar al objeto.
Verificando si el objeto es un arreglo:
is.array(a)
## [1] TRUE
Marcos de Datos: DataFrames
Son similares a los arreglos pero admiten columnas de diferentes tipos. Por ejemplo:
data<-data.frame(ID=c("gen0","genB","genZ"),
suj1=c(10,25,33),
suj2=c(NA,34,15),
oncogen=c(TRUE,TRUE,FALSE),
loc=c(1,30,125))
data
## ID suj1 suj2 oncogen loc
## 1 gen0 10 NA TRUE 1
## 2 genB 25 34 TRUE 30
## 3 genZ 33 15 FALSE 125
Distintas formas de crear un dataframe:
y=matrix(1:9,ncol=3)
as.data.frame(y)
## V1 V2 V3
## 1 1 4 7
## 2 2 5 8
## 3 3 6 9
Factores
Es un tipo de vector para datos cualitativos (o categóricos). Las variables cuantitativas se representan en R mediante un vector, mientras que para las variables cualitativas se utilizan factores.Por ejemplo:
f1<-factor(c(1,2,2,1,1,2,1,2,1));f1
## [1] 1 2 2 1 1 2 1 2 1
## Levels: 1 2
Podemos generar un factor usando la función gl() y colnames() al especificar los niveeles, las observaciones de cada nivel y su patrón así como el total de elementos en el vector de tipo factor.
gl(3,5,15) # 3 niveles con 5 repeticiones cada uno
## [1] 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3
## Levels: 1 2 3
gl(3,1,15) # 3 niveles que repite 15/3 veces la secuencia de 1 a 3
## [1] 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
## Levels: 1 2 3
Verificando si el objeto es un factor:
is.factor(f1)
## [1] TRUE
Listas
Es un vector generalizado, es decir, sus componentes pueden ser también listas, o pueden ser de distinto tipo. No tienen estructura.Las listas son muy útiles cuando queremos agrupar distintos tipos de objetos y de distinto tamaño. Por ejemplo:
# Escalar
escalar <- 42
# Vector
vector <- c(1, 2, 3, 4, 5)
# Matriz
matriz <- matrix(1:9, nrow = 3, ncol = 3)
# Arreglo
arreglo <- array(1:12, dim = c(2, 3, 2))
# Dataframe
dataframe <- data.frame(
Mes = c("Vendimiario", "Brumario", "Pluvioso"),
Fecha = c("22sep_21Oct", "22Oct_20Nov","20Ene_18Feb"),
Evento = c("Vendimia", "Bruma", "Lluvia")
)
# Lista
lista_interna <- list(a = 1, b = "texto", c = TRUE)
# Lista que contiene todos los elementos anteriores
mi_lista <- list(
Escalar = escalar,
Vector = vector,
Matriz = matriz,
Arreglo = arreglo,
Dataframe = dataframe,
Lista = lista_interna
)
# Mostrar la lista
print(mi_lista)
## $Escalar
## [1] 42
##
## $Vector
## [1] 1 2 3 4 5
##
## $Matriz
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
##
## $Arreglo
## , , 1
##
## [,1] [,2] [,3]
## [1,] 1 3 5
## [2,] 2 4 6
##
## , , 2
##
## [,1] [,2] [,3]
## [1,] 7 9 11
## [2,] 8 10 12
##
##
## $Dataframe
## Mes Fecha Evento
## 1 Vendimiario 22sep_21Oct Vendimia
## 2 Brumario 22Oct_20Nov Bruma
## 3 Pluvioso 20Ene_18Feb Lluvia
##
## $Lista
## $Lista$a
## [1] 1
##
## $Lista$b
## [1] "texto"
##
## $Lista$c
## [1] TRUE
Importancia de la Indexación
La indexación en R es fundamental para manipular y analizar datos de manera eficiente. Aquí te explico la importancia de la indexación en diferentes estructuras de datos:
Vectores
Matrices
Arreglos
Marcos de datos (Dataframes):
Indexación de Vectores
vector <- c(10, 20, 30, 40, 50)
primer_elemento <- vector[1] #extraer primer elemento
print(primer_elemento) # imprime el primer elemento
## [1] 10
ultimo_elemento <- vector[length(vector)] #extraer último elemento
print(ultimo_elemento)
## [1] 50
tercer_elemento <- vector[3] #extrae el tercer elemento
print(tercer_elemento)
## [1] 30
vector_sin_elementos <- vector[-c(2, 4)] # elimina elementos especificados
print(vector_sin_elementos)
## [1] 10 30 50
vector[c(2, 4)] <- c(25, 45) # sustituye dos elementos del vector
print(vector)
## [1] 10 25 30 45 50
maximo <- max(vector) # extrae el máximo
minimo <- min(vector) # extrae el mínimo
print(c(maximo,minimo))
## [1] 50 10
vector_nulo <- c() # crea vector nulo
print(vector_nulo)
## NULL
vector_na <- c(10, 20, NA, 40, 50) # creando un vector con un faltante
tiene_na <- any(is.na(vector_na)) # busca un faltante en el vector
print(tiene_na) # imprime si tiene al menos un faltante
## [1] TRUE
Indexación de Matrices
matriz <- matrix(1:9, nrow = 3, ncol = 3);matriz # la matriz
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
fila2 <- matriz[2, ];fila2 # extraer la fila 2
## [1] 2 5 8
columna3 <- matriz[, 3];columna3 # extraer columna 3
## [1] 7 8 9
elemento <- matriz[2, 3];elemento # extrae elemento de fila 2 columna 3
## [1] 8
matriz_sin_fila2 <- matriz[-2, ] ; matriz_sin_fila2# eliminando fila 2
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 3 6 9
matriz_sin_columna3 <- matriz[, -3];matriz_sin_columna3 # eliminando columna 3
## [,1] [,2]
## [1,] 1 4
## [2,] 2 5
## [3,] 3 6
matriz[1, 1] <- 99; matriz # sustituyendo el elemento de fila y columna 1
## [,1] [,2] [,3]
## [1,] 99 4 7
## [2,] 2 5 8
## [3,] 3 6 9
maximo <- max(matriz);maximo # extrayendo el máximo de la matriz
## [1] 99
minimo <- min(matriz);minimo # extrayendo el mínimo de la matriz
## [1] 2
matriz_nula <- matrix(0, nrow = 3, ncol = 3); matriz_nula # matriz nula
## [,1] [,2] [,3]
## [1,] 0 0 0
## [2,] 0 0 0
## [3,] 0 0 0
tiene_na <- any(is.na(matriz)); tiene_na # verificando si tiene faltantes
## [1] FALSE
diagonal <- diag(matriz);diagonal # extrae la diagonal de la matriz
## [1] 99 5 9
Indexación de Marcos de Datos
df <- data.frame(
genotipo = gl(3,3,9,labels=c("Biloxi","Victoria", "Emerald") ),
diametro = c(15,12,18,12,10,9,12,12,10),
biomasa=c(2.5,2.8,3.2,3.5,3.2,2.8,4.1,3.5,3.0)) # los datos
df
## genotipo diametro biomasa
## 1 Biloxi 15 2.5
## 2 Biloxi 12 2.8
## 3 Biloxi 18 3.2
## 4 Victoria 12 3.5
## 5 Victoria 10 3.2
## 6 Victoria 9 2.8
## 7 Emerald 12 4.1
## 8 Emerald 12 3.5
## 9 Emerald 10 3.0
fila2 <- df[2, ];fila2 # extrae segunda fila
## genotipo diametro biomasa
## 2 Biloxi 12 2.8
columna_biomasa<- df$biomasa;columna_biomasa #" extrae columna especificada"
## [1] 2.5 2.8 3.2 3.5 3.2 2.8 4.1 3.5 3.0
elemento <- df[2, "genotipo"];elemento # extrae elemento de fila y columna especificada
## [1] Biloxi
## Levels: Biloxi Victoria Emerald
df_sin_fila2 <- df[-2, ];df_sin_fila2 # elimina segunda fila
## genotipo diametro biomasa
## 1 Biloxi 15 2.5
## 3 Biloxi 18 3.2
## 4 Victoria 12 3.5
## 5 Victoria 10 3.2
## 6 Victoria 9 2.8
## 7 Emerald 12 4.1
## 8 Emerald 12 3.5
## 9 Emerald 10 3.0
df_sin_columna_diametro <- df[, -which(names(df) == "diametro")];df_sin_columna_diametro #elimina columna especificada
## genotipo biomasa
## 1 Biloxi 2.5
## 2 Biloxi 2.8
## 3 Biloxi 3.2
## 4 Victoria 3.5
## 5 Victoria 3.2
## 6 Victoria 2.8
## 7 Emerald 4.1
## 8 Emerald 3.5
## 9 Emerald 3.0
df[1, "diametro"] <- 16; df # sustituye un valor de una columna en fila especificada
## genotipo diametro biomasa
## 1 Biloxi 16 2.5
## 2 Biloxi 12 2.8
## 3 Biloxi 18 3.2
## 4 Victoria 12 3.5
## 5 Victoria 10 3.2
## 6 Victoria 9 2.8
## 7 Emerald 12 4.1
## 8 Emerald 12 3.5
## 9 Emerald 10 3.0
max_biomasa <- max(df$biomasa);max_biomasa # halla el máximo de una columna especificada
## [1] 4.1
min_biomasa <- min(df$biomasa);min_biomasa # halla el mínimo de una columna especificada
## [1] 2.5
df_nulo <- data.frame();df_nulo #data.frame vació
## data frame with 0 columns and 0 rows
tiene_duplicados <- any(duplicated(df));tiene_duplicados # busca duplicados
## [1] FALSE
df_por_genotipo <- split(df, df$genotipo);df_por_genotipo # divide el marco por genotipos
## $Biloxi
## genotipo diametro biomasa
## 1 Biloxi 16 2.5
## 2 Biloxi 12 2.8
## 3 Biloxi 18 3.2
##
## $Victoria
## genotipo diametro biomasa
## 4 Victoria 12 3.5
## 5 Victoria 10 3.2
## 6 Victoria 9 2.8
##
## $Emerald
## genotipo diametro biomasa
## 7 Emerald 12 4.1
## 8 Emerald 12 3.5
## 9 Emerald 10 3.0
primeras_filas <- head(df);primeras_filas # primeros elementos del marco
## genotipo diametro biomasa
## 1 Biloxi 16 2.5
## 2 Biloxi 12 2.8
## 3 Biloxi 18 3.2
## 4 Victoria 12 3.5
## 5 Victoria 10 3.2
## 6 Victoria 9 2.8
ultimas_filas <- tail(df);ultimas_filas # últimos elementos del marco
## genotipo diametro biomasa
## 4 Victoria 12 3.5
## 5 Victoria 10 3.2
## 6 Victoria 9 2.8
## 7 Emerald 12 4.1
## 8 Emerald 12 3.5
## 9 Emerald 10 3.0
filas_rango <- df[2:3, ];filas_rango #extrae todas las columnas para un rango de filas
## genotipo diametro biomasa
## 2 Biloxi 12 2.8
## 3 Biloxi 18 3.2
columnas_rango <- df[, 1:2];columnas_rango #extrae todas las filas para un rango de columnas
## genotipo diametro
## 1 Biloxi 16
## 2 Biloxi 12
## 3 Biloxi 18
## 4 Victoria 12
## 5 Victoria 10
## 6 Victoria 9
## 7 Emerald 12
## 8 Emerald 12
## 9 Emerald 10
columnas_duplicadas <- any(duplicated(names(df)));columnas_duplicadas #busca columnas duplicadas
## [1] FALSE
comunes <- intersect(df$diametro, df$biomasa);comunes # busca elementos comunes en dos columnas
## numeric(0)
Nota: En R, un resultado como numeric(0) indica que el resultado es un vector numérico vacío. Esto significa que no contiene ningún elemento. Este tipo de resultado puede ocurrir en varias situaciones, como cuando se realiza una operación de filtrado que no encuentra ningún valor que cumpla con las condiciones especificadas.
Indexación de Listas
mi_lista <- list(
vector = c(1, 2, 3, 4, 5),
matriz = matrix(1:9, nrow = 3, ncol = 3),
dataframe = data.frame(A = 1:3, B = c("a", "b", "c"))
)
mi_lista # la lista
## $vector
## [1] 1 2 3 4 5
##
## $matriz
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
##
## $dataframe
## A B
## 1 1 a
## 2 2 b
## 3 3 c
componente_vector <- mi_lista$vector ; componente_vector # extrae el vector de la lista
## [1] 1 2 3 4 5
columna_matriz <- mi_lista$matriz[, 2];columna_matriz # extrae una columna del objeto matriz dentro de la lista
## [1] 4 5 6
elemento_vector <- mi_lista$vector[3];elemento_vector #extrae un elemento del objeto vector dentro de la lista
## [1] 3
mi_lista$matriz <- mi_lista$matriz[-2, ]; mi_lista$matriz #Eliminar una fila de una matriz en la lista
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 3 6 9
mi_lista$matriz <- mi_lista$matriz[, -3]; mi_lista$matriz #Eliminar una columna de una matriz en la lista
## [,1] [,2]
## [1,] 1 4
## [2,] 3 6
mi_lista$vector[1] <- 99; mi_lista #Sustituir elementos de una lista en la lista
## $vector
## [1] 99 2 3 4 5
##
## $matriz
## [,1] [,2]
## [1,] 1 4
## [2,] 3 6
##
## $dataframe
## A B
## 1 1 a
## 2 2 b
## 3 3 c
max_vector <- max(mi_lista$vector); max_vector#Buscar el máximo en un vector numérico en la lista
## [1] 99
min_columna_matriz <- min(mi_lista$matriz[, 1]);min_columna_matriz #Buscar el mínimo de una columna de una matriz en la lista
## [1] 1
lista_nula <- list(); lista_nula #lista vacía
## list()
tiene_duplicados <- any(duplicated(mi_lista$dataframe)); tiene_duplicados #Notar si tiene filas duplicadas en la matriz de una lista
## [1] FALSE
sublistas <- split(mi_lista, c(1, 2, 1)); sublistas #Partir la lista en dos sublistas
## $`1`
## $`1`$vector
## [1] 99 2 3 4 5
##
## $`1`$dataframe
## A B
## 1 1 a
## 2 2 b
## 3 3 c
##
##
## $`2`
## $`2`$matriz
## [,1] [,2]
## [1,] 1 4
## [2,] 3 6
primer_objeto <- mi_lista[[1]]; primer_objeto #Mostrar el primer objeto de la lista:
## [1] 99 2 3 4 5
ultimo_objeto <- mi_lista[[length(mi_lista)]]; ultimo_objeto #Mostrar el último objeto de la lista
## A B
## 1 1 a
## 2 2 b
## 3 3 c
Desde Excel
Usualmente los conjuntos de datos los tenemos almacenados en hojas de cálculo de excel, por lo que se requiere de su importanción a R para trabajarlos en este entorno. La imagen siguiente muestra las ventanas a desplegar desde RStudio:
Al hacer clic al campo “From Excel” se despliega la siguiente ventana, donde se espera busquemos el archivo de interés haciendo clic al botón “Browse…”
Aquí seleccionamos el archivo de excel llamado “soc” el cual es de extensión “.xlsx”, luego hacemis clic en “open”
Con esto aparece la ruta y una previsualización de los datos del archivo, tal como se muestra en la siguiente imagen:
Para terminar el proceso de importación se deben ajustar los campos que aparecen en la misma ventana pero que solo mostramos en la siguiente imagen:
Descripción de Campos
Uan vez ajustado nuestro caso, este campo queda como:
La nueva pestaña despues de hacer clic al botón “import” luce como:
Ya podemos pedir la clase de objeto que importamos:
library(readxl)
soc <- read_excel("C:/Users/57316/Desktop/TABSET/soc.xlsx",
sheet = "soc")
class(soc)
## [1] "tbl_df" "tbl" "data.frame"
y allí encontramos por ahora la opción “data.frame” y otras dos que veremos luego.Si queremos acceder a las variables del data.frame llamado “soc” solo tenemos que escribir el nombre del data.frame en el chunk de R, que es el campo que aparece con una pequeña flecha a la derecha que permite ejecutar solo el código de este trozo de R y aparece un engranaje que podemos configurar para generar las salidas a nuestro gusto. En nuestro caso accedimos a la variable “Sand”, la cual mostrará todos los datos contenidos en la variable
soc$Sand
## [1] 91.94 16.40 22.82 10.60 24.68 12.82 44.96 28.90 32.96 42.82 60.82 58.90
## [13] 42.82 50.60 64.82 64.96 54.96 68.96 46.96 24.82 72.82 52.96 56.76 72.82
## [25] 80.76 40.68 50.82 36.68 56.60 44.40 69.82 26.32 57.96 66.10 60.10 56.10
## [37] 50.24 52.10 48.10 48.10 52.10 32.10 44.04 42.10 40.04 32.24 42.32 32.32
## [49] 34.46 26.60 76.76 72.82 40.82 38.76 24.82 48.96 60.76 40.82 34.76 36.82
## [61] 42.60 36.76 26.76 30.82 40.60 28.10 18.82 44.60 36.82 32.60 40.60 50.82
## [73] 40.76 44.82 58.90 73.12 59.18 85.12 49.18 57.26 87.32 33.32 41.48 41.48
## [85] 55.54 51.54 49.62 21.62 41.54 77.54 47.48 77.18 21.54 47.32 31.48 43.32
## [97] 49.48 73.32 41.32 59.32 67.54 53.48 71.32 31.18 49.12 69.12 65.04 56.90
## [109] 40.90 11.88 52.82 60.82 74.82 34.96 44.96 40.96 36.82 56.82 54.82 72.76
## [121] 76.76 46.82 22.76 56.68 68.82 54.60 73.04 66.96 53.26 53.26 57.32 61.48
## [133] 41.32 25.18 21.18 41.18 39.12 21.18 61.26 31.32 29.18 25.18 27.18 17.12
## [145] 33.54 23.18 29.18 33.18 23.32 37.32 25.18
Estructura del objeto
La función str() que se muestra, permite ver el nombre de cada variable, su tipo y dimensión.
str(soc)
## tibble [151 × 8] (S3: tbl_df/tbl/data.frame)
## $ LONG1: num [1:151] -73.6 -73.6 -73.6 -73.6 -73.6 ...
## $ LAT1 : num [1:151] 4.22 4.21 4.21 4.21 4.21 ...
## $ Sand : num [1:151] 91.9 16.4 22.8 10.6 24.7 ...
## $ Clay : num [1:151] 7.7 31.6 27.9 30 32 ...
## $ Silt : num [1:151] 0.36 52 49.28 59.44 43.36 ...
## $ SOC : num [1:151] 2 1.78 2.44 2.81 2.4 ...
## $ DA : num [1:151] 1.31 1.23 1.18 1.18 1.27 ...
## $ dem : num [1:151] 533 532 528 510 514 ...
Atributos del Objeto
La función attributes() que se muestra, permite ver los atributos que se pueden extraer del objeto.
attributes(soc)
## $class
## [1] "tbl_df" "tbl" "data.frame"
##
## $row.names
## [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
## [19] 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
## [37] 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
## [55] 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
## [73] 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
## [91] 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
## [109] 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
## [127] 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
## [145] 145 146 147 148 149 150 151
##
## $names
## [1] "LONG1" "LAT1" "Sand" "Clay" "Silt" "SOC" "DA" "dem"
Si quisiéramos extraer los nombres del data.frame entonces bastará escribir:
names(soc)
## [1] "LONG1" "LAT1" "Sand" "Clay" "Silt" "SOC" "DA" "dem"
Valores faltantes
Hace rato, en la previasualización notamos algunos faltantes en una de las columnas, si queremos encontrarla, debemos escribir
which(is.na(soc),arr.ind = T)
## row col
## [1,] 11 7
## [2,] 12 7
## [3,] 15 7
## [4,] 16 7
## [5,] 25 7
## [6,] 35 7
## [7,] 39 7
## [8,] 57 7
## [9,] 58 7
## [10,] 66 7
## [11,] 112 7
Lo cual nos dirá la fila y columna donde tenemos valores faltantes. En este caso todos pertenecen a la columna 7, es decir:
names(soc)[7]
## [1] "DA"
como “names(soc)” es un vector de caracterés, al indexarlo en la posición 7 tendremos el nombre de la columna con faltantes, la cual se asocia a DA que representa la densidad aparente.
Operaciones con Faltantes
Cuando utilizamos operaciones sobre vectores con valores ausentes, el resultado será NA a no ser que especifiquemos que no los considere en los cálculos. Por ejemplo, para el caso del promedio:
mean(soc$DA ,na.rm=TRUE) #omitiendo los faltantes
## [1] 1.295109
mean(soc$DA )
## [1] NA
Vectores, Matrices y Marcos de Datos
Podemos tomar vectores, matrices o data frames y combinarlos mediante filas ( para igual número de columnas) o columnas ( para igual número de filas).
v1= seq(1,10,1) # secuencia de 10 números que empieza en 1, termina en 10 y se incrementa cada 1
v2 = 10:1 # secuencia de 10 números que empieza en 10, termina en 1 y se decrementa hasta llegar a 1
una_fila =rbind(v1,v2);una_fila # combina en una fila todos los elementos de ambos vectores
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## v1 1 2 3 4 5 6 7 8 9 10
## v2 10 9 8 7 6 5 4 3 2 1
dos_columnas =cbind(v1,v2);dos_columnas # combina en dos columnas todos los elementos de ambos vectores
## v1 v2
## [1,] 1 10
## [2,] 2 9
## [3,] 3 8
## [4,] 4 7
## [5,] 5 6
## [6,] 6 5
## [7,] 7 4
## [8,] 8 3
## [9,] 9 2
## [10,] 10 1
Podemos utilizar la función para combinar merge() data frames basados el columnas o filas comunes (no se necesita la misma dimensionalidad). Esta función identifica columnas o filas que son comunes entre los dos data frame para unirlas. Los argumentos a ingresar son e los data frame, los nombres de las columnas comunes a ambos conjuntos de datos, especifican el tipo de unión a realizar.
Crearemos unos datos ficticios para ejemplificar la función. Tenemos una base de datos con las palmas visitadas en busca de abortos de racimos o presencia de plumero y otra base de datos con el estado de la palma en la visita anterior. Queremos unir las bases de datos.
df1 = data.frame(Palma = c(1:6),
Status = c(rep("Sana", 2), rep("Plumero", 2),rep("Aborto", 2) ))
df1
## Palma Status
## 1 1 Sana
## 2 2 Sana
## 3 3 Plumero
## 4 4 Plumero
## 5 5 Aborto
## 6 6 Aborto
df2 = data.frame(Palma = c(2, 4, 6),
Status0 = c(rep("Sana", 2), rep("Aborto", 1)))
df2
## Palma Status0
## 1 2 Sana
## 2 4 Sana
## 3 6 Aborto
La función merge() intersecta ambos marcos por la única variable común , a saber, la palma y crea un nuevo marco con los tres atributos.
df3=merge(df1,df2) #natural Join
df3
## Palma Status Status0
## 1 2 Sana Sana
## 2 4 Plumero Sana
## 3 6 Aborto Aborto
Si embargo, se pudieron haber unido así hayan filas no comunes, esto se logra haciendo
df3b=merge(x = df1, y = df2, by = "Palma", all = TRUE) # full outer join
df3b
## Palma Status Status0
## 1 1 Sana <NA>
## 2 2 Sana Sana
## 3 3 Plumero <NA>
## 4 4 Plumero Sana
## 5 5 Aborto <NA>
## 6 6 Aborto Aborto
Sin embargo, se puede espeficicar si se quiere que aparezca toda la información del primer marco o del segundo, por ejemplo:
df3c=merge(x = df1, y = df2, by = "Palma", all.x = TRUE) #left outer join
df3c
## Palma Status Status0
## 1 1 Sana <NA>
## 2 2 Sana Sana
## 3 3 Plumero <NA>
## 4 4 Plumero Sana
## 5 5 Aborto <NA>
## 6 6 Aborto Aborto
df3d=merge(x = df1, y = df2, by = "Palma", all.y = TRUE) #right outer join
df3d
## Palma Status Status0
## 1 2 Sana Sana
## 2 4 Plumero Sana
## 3 6 Aborto Aborto
Veamos ahora cómo trabajan con los datos perdidos.
x <- data.frame(k1 = c(NA,NA,3,4,5), k2 = c(1,NA,NA,4,5),
data = 1:5)
x
## k1 k2 data
## 1 NA 1 1
## 2 NA NA 2
## 3 3 NA 3
## 4 4 4 4
## 5 5 5 5
y <- data.frame(k1 = c(NA,2,NA,4,5), k2 = c(NA,NA,3,4,5),
data = 1:5)
y
## k1 k2 data
## 1 NA NA 1
## 2 2 NA 2
## 3 NA 3 3
## 4 4 4 4
## 5 5 5 5
merge(x, y, by = c("k1","k2")) # toma las filas duplicadas en ambos marcos
## k1 k2 data.x data.y
## 1 4 4 4 4
## 2 5 5 5 5
## 3 NA NA 2 1
merge(x, y, by = "k1") # intersecta por k1 , pues k1 en x (NA,3,4,5) y k1 en y (NA,2,4,5): comun (NA,4,5)
## k1 k2.x data.x k2.y data.y
## 1 4 4 4 4 4
## 2 5 5 5 5 5
## 3 NA 1 1 NA 1
## 4 NA 1 1 3 3
## 5 NA NA 2 NA 1
## 6 NA NA 2 3 3
merge(x, y, by = "k2") # intersecta por k2 , pues k2 en x (NA,1,4,5) y k2 en y (NA,3,4,5): comun (NA,4,5)
## k2 k1.x data.x k1.y data.y
## 1 4 4 4 4 4
## 2 5 5 5 5 5
## 3 NA NA 2 NA 1
## 4 NA NA 2 2 2
## 5 NA 3 3 NA 1
## 6 NA 3 3 2 2
merge(x, y, by = "k2", incomparables = NA) #intersecta por k2 , pues k2 en x (1,4,5) y k2 en y (3,4,5): común (4,5)
## k2 k1.x data.x k1.y data.y
## 1 4 4 4 4 4
## 2 5 5 5 5 5
Vectores, Matrices y Marcos de Datos
Todas estas funciones nos sirven para dividir una base de datos en función de determinadas condiciones. La función stack() une (o apila) múltiples vectores en un único vector, mientras que la función unstack() invierte esta operación.
Considere el siguiente ejemplo donde tenemos los resultados de un experimento donde se comparan los rendimientos (masa seca por planta) obtenidos bajo 3 condiciones: control y dos diferentes tratamientos. Queremos dar otro formato a los datos.
require(stats)
head(PlantGrowth)
## weight group
## 1 4.17 ctrl
## 2 5.58 ctrl
## 3 5.18 ctrl
## 4 6.11 ctrl
## 5 4.50 ctrl
## 6 4.61 ctrl
dim(PlantGrowth)
## [1] 30 2
La función formula() relaciona el peso como función (virgulilla) del grupo.
formula(PlantGrowth) # fórmula por defecto
## weight ~ group
La función levels() muestra los niveles de la variable que agrupa.
levels(PlantGrowth$group) # indica los niveles del factor grupo
## [1] "ctrl" "trt1" "trt2"
Como todos los pesos vienen en un único vector (formato largo), se pueden particionar por los tres tratamientos y tener el formato ancho haciendo:
pg=unstack(PlantGrowth);pg
## ctrl trt1 trt2
## 1 4.17 4.81 6.31
## 2 5.58 4.17 5.12
## 3 5.18 4.41 5.54
## 4 6.11 3.59 5.50
## 5 4.50 5.87 5.37
## 6 4.61 3.83 5.29
## 7 5.17 6.03 4.92
## 8 4.53 4.89 6.15
## 9 5.33 4.32 5.80
## 10 5.14 4.69 5.26
Esto se logra automáticamente sobre la variable posterior a la virgulilla en la fórmula. El nuevo objeto sigue siendo un marco de datos.
class(pg)
## [1] "data.frame"
Si queremos reversar esta operación basta con agrupar con la función stack():
stack(pg)
## values ind
## 1 4.17 ctrl
## 2 5.58 ctrl
## 3 5.18 ctrl
## 4 6.11 ctrl
## 5 4.50 ctrl
## 6 4.61 ctrl
## 7 5.17 ctrl
## 8 4.53 ctrl
## 9 5.33 ctrl
## 10 5.14 ctrl
## 11 4.81 trt1
## 12 4.17 trt1
## 13 4.41 trt1
## 14 3.59 trt1
## 15 5.87 trt1
## 16 3.83 trt1
## 17 6.03 trt1
## 18 4.89 trt1
## 19 4.32 trt1
## 20 4.69 trt1
## 21 6.31 trt2
## 22 5.12 trt2
## 23 5.54 trt2
## 24 5.50 trt2
## 25 5.37 trt2
## 26 5.29 trt2
## 27 4.92 trt2
## 28 6.15 trt2
## 29 5.80 trt2
## 30 5.26 trt2
Si queremos omitir un tratamiento (por ejemplo el control) hacemos:
stack(pg,select=-ctrl) # si queremos omitir un vector
## values ind
## 1 4.81 trt1
## 2 4.17 trt1
## 3 4.41 trt1
## 4 3.59 trt1
## 5 5.87 trt1
## 6 3.83 trt1
## 7 6.03 trt1
## 8 4.89 trt1
## 9 4.32 trt1
## 10 4.69 trt1
## 11 6.31 trt2
## 12 5.12 trt2
## 13 5.54 trt2
## 14 5.50 trt2
## 15 5.37 trt2
## 16 5.29 trt2
## 17 4.92 trt2
## 18 6.15 trt2
## 19 5.80 trt2
## 20 5.26 trt2
Cuando queremos tomar un subgrupo de vectores, matrices o data frame según una condición establecida, podemos utilizar la función subset() , además, las condiciones suelen formarse con los operadores lógicos.
subset(PlantGrowth, weight>5 & weight<5.2) # entre 5 y 5.2 sin incluir
## weight group
## 3 5.18 ctrl
## 7 5.17 ctrl
## 10 5.14 ctrl
## 22 5.12 trt2
subset(PlantGrowth, group=="trt1") # operador lógico == para buscar aquello que coincida con trt1
## weight group
## 11 4.81 trt1
## 12 4.17 trt1
## 13 4.41 trt1
## 14 3.59 trt1
## 15 5.87 trt1
## 16 3.83 trt1
## 17 6.03 trt1
## 18 4.89 trt1
## 19 4.32 trt1
## 20 4.69 trt1
Cuando deseamos dividir una base de datos según los grupos definidos en otra columna categórica , podemos utilizar la función split(). Primero agreguemos la columna “bloque” al margo, de modo que las 10 repeticiones de cada tratamiento se partan en dos bloques:
PlantGrowth$bloque=gl(2,5,30,labels = c("bloque1","bloque2"))
PlantGrowth$bloque
## [1] bloque1 bloque1 bloque1 bloque1 bloque1 bloque2 bloque2 bloque2 bloque2
## [10] bloque2 bloque1 bloque1 bloque1 bloque1 bloque1 bloque2 bloque2 bloque2
## [19] bloque2 bloque2 bloque1 bloque1 bloque1 bloque1 bloque1 bloque2 bloque2
## [28] bloque2 bloque2 bloque2
## Levels: bloque1 bloque2
Todo el marco es ahora:
PlantGrowth
## weight group bloque
## 1 4.17 ctrl bloque1
## 2 5.58 ctrl bloque1
## 3 5.18 ctrl bloque1
## 4 6.11 ctrl bloque1
## 5 4.50 ctrl bloque1
## 6 4.61 ctrl bloque2
## 7 5.17 ctrl bloque2
## 8 4.53 ctrl bloque2
## 9 5.33 ctrl bloque2
## 10 5.14 ctrl bloque2
## 11 4.81 trt1 bloque1
## 12 4.17 trt1 bloque1
## 13 4.41 trt1 bloque1
## 14 3.59 trt1 bloque1
## 15 5.87 trt1 bloque1
## 16 3.83 trt1 bloque2
## 17 6.03 trt1 bloque2
## 18 4.89 trt1 bloque2
## 19 4.32 trt1 bloque2
## 20 4.69 trt1 bloque2
## 21 6.31 trt2 bloque1
## 22 5.12 trt2 bloque1
## 23 5.54 trt2 bloque1
## 24 5.50 trt2 bloque1
## 25 5.37 trt2 bloque1
## 26 5.29 trt2 bloque2
## 27 4.92 trt2 bloque2
## 28 6.15 trt2 bloque2
## 29 5.80 trt2 bloque2
## 30 5.26 trt2 bloque2
Dividamos:
split(PlantGrowth$weight, f=PlantGrowth$bloque)
## $bloque1
## [1] 4.17 5.58 5.18 6.11 4.50 4.81 4.17 4.41 3.59 5.87 6.31 5.12 5.54 5.50 5.37
##
## $bloque2
## [1] 4.61 5.17 4.53 5.33 5.14 3.83 6.03 4.89 4.32 4.69 5.29 4.92 6.15 5.80 5.26
Observe que formula respeta el arreglo en que se meten los datos al marco.
formula(PlantGrowth)
## weight ~ group + bloque
¿Que pasa si reversamos el orden de las columnas al usar la función formula()
PlantGrowth_rev <- PlantGrowth[, c("bloque", "group", "weight")]
PlantGrowth_rev
## bloque group weight
## 1 bloque1 ctrl 4.17
## 2 bloque1 ctrl 5.58
## 3 bloque1 ctrl 5.18
## 4 bloque1 ctrl 6.11
## 5 bloque1 ctrl 4.50
## 6 bloque2 ctrl 4.61
## 7 bloque2 ctrl 5.17
## 8 bloque2 ctrl 4.53
## 9 bloque2 ctrl 5.33
## 10 bloque2 ctrl 5.14
## 11 bloque1 trt1 4.81
## 12 bloque1 trt1 4.17
## 13 bloque1 trt1 4.41
## 14 bloque1 trt1 3.59
## 15 bloque1 trt1 5.87
## 16 bloque2 trt1 3.83
## 17 bloque2 trt1 6.03
## 18 bloque2 trt1 4.89
## 19 bloque2 trt1 4.32
## 20 bloque2 trt1 4.69
## 21 bloque1 trt2 6.31
## 22 bloque1 trt2 5.12
## 23 bloque1 trt2 5.54
## 24 bloque1 trt2 5.50
## 25 bloque1 trt2 5.37
## 26 bloque2 trt2 5.29
## 27 bloque2 trt2 4.92
## 28 bloque2 trt2 6.15
## 29 bloque2 trt2 5.80
## 30 bloque2 trt2 5.26
formula(PlantGrowth_rev)
## bloque ~ group + weight
Nota: La fórmula ya no representa lo mismo, por lo que debe tenerse cuidado al respecto