pre code { color: #00008B; /* Azul oscuro */ }

Operaciones Básicas

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.

Operadores

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
  • El Máximo: \[ x_{(n)} = max(x)\]
max(pp) #máximo valor de pp
## [1] 36
  • El Mínimo: \[ x_{(1)} = min(x)\]
min(pp) #mínimo valor de pp
## [1] 0
  • El Rango: \[x_{(n)}-x_{(n)}=r(x) \] ” se imprime el mínimo y máximo y no la diferencia”
range(pp) #rango de valores de pp
## [1]  0 36
  • La suma: \[{\sum_{i=1}^{n}{x_i}}= sum({x})\]
sum(pp) #suma de todos los datos de pp
## [1] 563
  • El Promedio Aritmético: \[{{\sum_{i=1}^{n}{x_i}}\over{n}}=\bar{x}; i=1\cdots{n} \]
mean(pp)  #media de pp
## [1] 24.47826
  • La mediana: \[Prob(x \leq{\hat{x}})\geq{1/2} "y" Prob(x \geq{\hat{x}})\geq{1/2}\]
median(pp) #mediana de la pp
## [1] 25
  • Diferencias sucesivas de primer orden: \[ x_{i+1}-x_{i}; i=1\cdots{n-1}\]
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
  • Productoria: \[ x_{i}x_{2}.\cdots. x_{n}=\prod_{i=1}^{n}{x_i} ; i=1\cdots{n}\]
prod(pp) #productoria de tolos los valores de pp
## [1] 0
  • Suma acumulada: \[ x_{(1)},x_{(1)}+x_{(2)},x_{(1)}+x_{(2)}+x_{(3)},\cdots, \sum_{i=1}^{n}{x_i};i=1\cdots{n} \]
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
  • Varianza muestral: \[{{\sum_{i=1}^{n}(x_i-\bar{x_i})^2}\over{n-1}}=s^2\]
var(pp) #varianza de la pp
## [1] 89.26087
  • Raíz Cuadrada: \[\sqrt{x_i}\]
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
  • Desviación estándar muestral: \[\sqrt{{\sum(x_i-\bar{x_i})^2}\over{n-1}}=s\]
sd(pp) #desviación estándar de la pp
## [1] 9.447797
  • Cuartil inferior : \[Prob(x \leq{{q_{0.25}}})\geq{1/4} "y" Prob(x \geq{{q_{0.25}}})\geq{3/4}\]
quantile(pp,0.25) # cuartil inferior y superior de la pp
## 25% 
##  22
  • Cuartil superior : \[Prob(x \leq{{q_{0.75}}})\geq{3/4} "y" Prob(x \geq{{q_{0.75}}})\geq{1/4}\]
quantile(pp,0.25) # cuartil inferior y superior de la pp
## 25% 
##  22
  • Número de elementos de un vector : \[ n \]
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:

  • Cualquier:
any(pp<30)  #al menos un valor es menor a 30
## [1] TRUE
  • Todos:
all(pp>10) #Son todos los valores de pp mayores a 10
## [1] FALSE
  • Posición donde:
which(pp==25) #posiciones donde la precipitación vale 25
## [1]  2  4  7 13 16 21

Notación Científica

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}\)

Cifras

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

Objetos

(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

Indexación

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

    • Acceso rápido: Permite acceder a elementos específicos de un vector de manera rápida y sencilla.
    • Manipulación de datos: Facilita la modificación, eliminación y sustitución de elementos.
    • Condicionales: Permite seleccionar elementos que cumplen ciertas condiciones, lo que es útil para análisis de datos.
  • Matrices

    • Acceso bidimensional: Permite acceder a elementos específicos mediante índices de fila y columna.
    • Operaciones matemáticas: Facilita la realización de operaciones matemáticas y estadísticas en subconjuntos de datos.
    • Eficiencia: La indexación eficiente puede mejorar el rendimiento de los cálculos en matrices grandes.
  • Arreglos

    • Multidimensionalidad: Permite trabajar con datos en más de dos dimensiones, lo que es útil en análisis complejos.
    • Flexibilidad: Facilita la manipulación de datos en diferentes dimensiones, como en análisis de imágenes o datos espaciales.
  • Marcos de datos (Dataframes):

    • Acceso a columnas y filas: Permite acceder y manipular columnas y filas específicas, lo que es esencial para el análisis de datos tabulares.
    • Filtrado y selección: Facilita el filtrado de datos basados en condiciones específicas, lo que es crucial para el análisis exploratorio de datos.
    • Integración de datos: Permite combinar y fusionar datos de diferentes fuentes de manera eficiente

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

Importación

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

    • Name: Nombre del archivo: En nuestro caso es “soc”, sin embargo, si se desea cambiar aquí puede hacerlo
    • Sheet: Para seleccionar la hoja de interés. La nuestra se llama soc tambien.
    • Range y Max Rows usualmente no son de interés a menos que se desee trabajar con un subconjunto de datos
    • Skip: puede especificar si desea obviar los nombres de columna. En cero se mantienen.
    • NA: reconoce faltantes como NA pero podrían especificarse otras formas.
    • first row as names: deja la primera fila como nombres de columna
    • open data Viewer: hace que se despliegue una pestaña aparte con los datos
    • Code preview: muestra el código asociado a las opciones antes señaladas. Algunas personas copian este código haciendo clic al botón pequeño a la derecha superior de esta ventana. Al copiarlo lo pegan en el panel de script de R para no repetir este proveso de importación.

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

Combinando

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

Separando

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