9.4 Primeros pasos en R

9.4.1 Funciones y comandos elementales

Las entidades que crea R durante una sesión de trabajo se denominan objetos. Estos pueden ser números, cadenas, vectores, matrices, funciones o estructuras más generales construidas a partir de estos elementos. Estos objetos se guardan por nombre y se almacenan en un área dedicada llamada “espacio de trabajo” o environment. En cualquier momento, es posible verificar los objetos disponibles en el espacio de trabajo usando el comando:

ls()

Para eliminar un objeto del espacio de trabajo, se usa la función rm(). La función espera el nombre del objeto que se desea eliminar como argumento. Suponiendo que hay un objeto llamado “cosa”, puede eliminarse con el comando:

rm(cosa)

Al iniciar una nueva sesión de trabajo, se recomienda retirar los objetos existentes en el área de trabajo. Un comando útil para este propósito es:

rm(list = ls())

Se puede almacenar el espacio de trabajo con la función:

save.image()

Esto guarda todos los objetos contenidos en el espacio de trabajo en un archivo binario “.Rdata”. La opción predeterminada se puede cambiar especificando en la llamada a save.image() el nombre, por ejemplo, “myfile.Rdata”, que desea darle al archivo.

save.image(archive = "myfile.Rdata")

El espacio de trabajo original se puede restaurar con la ayuda de la función:

load(".RData")

o, si se ha optado por un nombre diferente al predeterminado:

load("ilmiofile.Rdata")

Las funciones:

savehistory()
loadhistory()

permiten guardar en formato ASCII y recargar en R el historial de los comandos enviados. El argumento de archivo que permite especificar un nombre que no sea la elección predeterminada, es “.Rhistory”.

Finalmente, la función setwd() permite cambiar la carpeta de trabajo. Es una buena idea dedicar una carpeta separada a cada proyecto en el que esté trabajando para evitar la superposición de datos. El directorio de trabajo actual se puede ver con el comando getwd().

Los comandos básicos constan de expresiones o asignaciones. Si el comando es una expresión, R devuelve el resultado de la evaluación, como se muestra en los siguientes ejemplos:

12 > 10
[1] TRUE
1 + 2 + 3
[1] 6
2 + 3 * 4
[1] 14
3/2 + 1
[1] 2.5
2 + (3 * 4)
[1] 14
(2 + 3) * 4
[1] 20
4 * 3^3
[1] 108

Todas las funciones matemáticas que normalmente se encuentran en una calculadora de bolsillo están disponibles en R en forma de funciones básicas, que se recuerdan en la siguiente tabla:

  • sqrt —> raíz cuadrada

  • abs —> valor absoluto

  • sin,cos,tan —> funciones trigonométricas

  • asin,acos,atan —> funciones trigonométricas inversas

  • exp,log —> exponenciales y logaritmos naturales

sqrt(2)
[1] 1.4
sin(3.14159)
[1] 0.0000027
sin(pi)
[1] 0.00000000000000012
sqrt(sin(45 * pi/180))
[1] 0.84

Una asignación evalúa una expresión guardando el resultado en un objeto con un nombre. La asignación se realiza mediante el símbolo <- o el símbolo =. También se puede asignar de izquierda a derecha con el símbolo ->. El resultado de una asignación no se muestra automáticamente. El usuario puede verlo recordando el nombre del objeto. Los objetos creados a través de una asignación se pueden reutilizar en expresiones y asignaciones posteriores, como se muestra en los siguientes ejemplos:

x <- sqrt(2)
x
[1] 1.4
x^3
[1] 2.8
y <- x^3
x <- 10
x > 10
[1] FALSE
x <= 10
[1] TRUE
tf <- x > 10
tf
[1] FALSE

9.4.2 Valores y vectores

Para asignarle un valor a una variable, no es necesario utilizar espacios ni símbolos, excepto # . o _ en el nombre de la variable:

mi_valor <- 30  # número
un_valor <- "vaca"  # caracteres
el_valor <- FALSE  # booleano

Para crear un vector, se usa la función c():

x <- c(2, 3, 5, 7, 11)
x
[1]  2  3  5  7 11

El vector puede contener texto o valores numéricos:

mi_vector <- c(6, 12, 80, 120)
mi_vector <- c("María", "Esteban", "Juan")

Si el vector contiene muchos elementos, puede ser más conveniente usar la función scan(), que permite ingresarlos uno por uno a través de la consola:

x <- scan()
1:1
2:6
3:3
4:4
5:2

Para crear una secuencia de números, puede usar el comando a:b:

xx <- 1:10

xx
 [1]  1  2  3  4  5  6  7  8  9 10
xx <- 100:1
xx
  [1] 100  99  98  97  96  95  94  93  92  91  90  89  88  87  86  85  84  83
 [19]  82  81  80  79  78  77  76  75  74  73  72  71  70  69  68  67  66  65
 [37]  64  63  62  61  60  59  58  57  56  55  54  53  52  51  50  49  48  47
 [55]  46  45  44  43  42  41  40  39  38  37  36  35  34  33  32  31  30  29
 [73]  28  27  26  25  24  23  22  21  20  19  18  17  16  15  14  13  12  11
 [91]  10   9   8   7   6   5   4   3   2   1

También se pueden crear vectores que contienen elementos repetidos:

rep(2, times = 3)
[1] 2 2 2
rep(2, 3)
[1] 2 2 2
a <- c(rep(2, 3), 4, 5, rep(1, 5))
a
 [1] 2 2 2 4 5 1 1 1 1 1

Las operaciones aritméticas y lógicas básicas que se aplican a los escalares se pueden aplicar a los vectores:

x <- 1:10
x * 2
 [1]  2  4  6  8 10 12 14 16 18 20

Los elementos de un vector se pueden extraer utilizando corchetes [] e indicando la posición del elemento a extraer entre corchetes:

xx[7]
[1] 94

Incluso se pueden extraer más elementos al mismo tiempo:

xx[c(2, 3, 5, 7, 11)]
[1] 99 98 96 94 90
xx[85:91]
[1] 16 15 14 13 12 11 10

También se pueden guardar en nuevos vectores:

yy <- xx[c(1, 2, 4, 8, 16, 32, 64)]
yy
[1] 100  99  97  93  85  69  37

Si los indicadores entre corchetes van precedidos de un signo negativo, los elementos correspondientes se eliminan del vector:

x <- c(1, 2, 4, 8, 16, 32)
x
[1]  1  2  4  8 16 32
x[-4]
[1]  1  2  4 16 32

Al ingresar una variable a la consola, esta mostrará su contenido:

mi_vector
[1] "María"   "Esteban" "Juan"   

La función length() sirve para obtener el número de elementos en un vector o en una lista de objetos:

length(mi_vector)
[1] 3

9.4.3 Matrices y listas

Una variable indexada (array) es una colección de datos, por ejemplo numéricos, indexada por varios índices. R permite crear y manipular variables indexadas en general y en particular, matrices.

Las matrices se crean utilizando la función matrix(). En su forma más simple, el uso de la función implica especificar un vector que contiene los elementos de la matriz y el número de filas o columnas de la matriz.

x <- matrix(c(2, 3, 5, 7, 11, 13), nrow = 3)
x
     [,1] [,2]
[1,]    2    7
[2,]    3   11
[3,]    5   13
y <- matrix(c(2, 3, 5, 7, 11, 13), ncol = 2)
y
     [,1] [,2]
[1,]    2    7
[2,]    3   11
[3,]    5   13

Las array pueden verse como matrices multidimensionales. Se crean usando la función array(). En su forma más simple, el uso de la función implica especificar un vector que contiene los elementos de la matriz y el número de elementos para cada dimensión usando el argumento dim.

w <- 1:20
ay <- array(w, dim = c(5, 2, 2))

ay
, , 1

     [,1] [,2]
[1,]    1    6
[2,]    2    7
[3,]    3    8
[4,]    4    9
[5,]    5   10

, , 2

     [,1] [,2]
[1,]   11   16
[2,]   12   17
[3,]   13   18
[4,]   14   19
[5,]   15   20

Hay que tener en cuenta que, de forma predeterminada, las matrices se forman insertando los distintos elementos por columna. Obviamente, la matriz se puede adquirir desde un archivo externo. Por ejemplo, suponiendo que el archivo matdata tiene el siguiente contenido:

1,24,32,36,33
2,16,44,34,33
3,20,31,43,32
4,23,35,37,35
5,27,40,40,31
6,19,43,32,37

El contenido del archivo se puede adquirir y asignar a una matriz de 6 × 5 con los comandos:

x2 <- scan("matdata", sep = ",")

mx <- matrix(x2, ncol = 5, byrow = TRUE)
mx

El argumento byrow = TRUE especifica que el contenido debe adquirirse por fila y no por columna.

La función dim() devuelve el tamaño (número de filas y número de columnas) de la matriz indicada como argumento:

dim(x)
[1] 3 2

En cuanto a los vectores, los elementos de una matriz se pueden extraer utilizando corchetes []. Para extraer un elemento de una matriz, se debe especificar su posición de fila y columna:

x[2, 1]
[1] 3
x[2, 2]
[1] 11

Para extraer una fila o columna completa, simplemente hay que especificar su posición:

x[, 1]
[1] 2 3 5
x[3, ]
[1]  5 13

Se pueden extraer subconjuntos de filas y/o columnas:

x <- matrix(1:16, ncol = 4)
x
     [,1] [,2] [,3] [,4]
[1,]    1    5    9   13
[2,]    2    6   10   14
[3,]    3    7   11   15
[4,]    4    8   12   16

También se puede crear una matriz compuesta por números usando la función matrix():

mi_matriz <- matrix(data = 1:10, # qué se incluye en la matriz
                    ncol = 5, # número de columnas
                    nrow = 20, # número de filas
                    byrow = TRUE) # incluir el input

mi_matriz
      [,1] [,2] [,3] [,4] [,5]
 [1,]    1    2    3    4    5
 [2,]    6    7    8    9   10
 [3,]    1    2    3    4    5
 [4,]    6    7    8    9   10
 [5,]    1    2    3    4    5
 [6,]    6    7    8    9   10
 [7,]    1    2    3    4    5
 [8,]    6    7    8    9   10
 [9,]    1    2    3    4    5
[10,]    6    7    8    9   10
[11,]    1    2    3    4    5
[12,]    6    7    8    9   10
[13,]    1    2    3    4    5
[14,]    6    7    8    9   10
[15,]    1    2    3    4    5
[16,]    6    7    8    9   10
[17,]    1    2    3    4    5
[18,]    6    7    8    9   10
[19,]    1    2    3    4    5
[20,]    6    7    8    9   10

Se puede indexar elementos de matrices en múltiples modos:

mi_matriz[1, ]  # las filas van seguidas de una coma. Primero filas y luego columnas[row,colum]
[1] 1 2 3 4 5
mi_matriz[, 5]  # columnas detrás de la coma
 [1]  5 10  5 10  5 10  5 10  5 10  5 10  5 10  5 10  5 10  5 10
mi_matriz[3, 3]
[1] 3

Se pueden crear nuevos vectores a partir de secciones de matrices:

val <- mi_matriz[3, 3]
val <- mi_matriz[, 3]

Hay algunas funciones útiles que se puede aprender para conocer más a fondo la matriz:

sum(mi_matriz)  # La suma de los elementos de la matriz
[1] 550
nrow(mi_matriz)  # El número de filas de la matriz
[1] 20
ncol(mi_matriz)  # El número de columnas de la matriz 
[1] 5

R tiene un conjunto de tipos de datos suficientemente diversificado para ser adecuado en la mayor cantidad de análisis. Los tipos que se encuentran con mayor frecuencia son lógicos (con los modos VERDADERO y FALSO), de caracteres (cadenas de caracteres) y numéricos. Las funciones con el prefijo is.type.of.data() o la función class() verifican a qué tipo de datos pertenece el objeto especificado como argumento.

x1 <- 1:3
is.logical(x1)
[1] FALSE
class(x1)
[1] "integer"

Para combinar objetos que no comparten la misma estructura, como cadenas de caracteres y vectores, es necesario utilizar una lista. Este es un tipo más general de estructura de vectores y matrices:

lista1 <- list(x, y)
lista1
[[1]]
     [,1] [,2] [,3] [,4]
[1,]    1    5    9   13
[2,]    2    6   10   14
[3,]    3    7   11   15
[4,]    4    8   12   16

[[2]]
     [,1] [,2]
[1,]    2    7
[2,]    3   11
[3,]    5   13

Una de las posibles formas de acceder a la información de una lista es mediante corchetes dobles:

lista1[[1]]
     [,1] [,2] [,3] [,4]
[1,]    1    5    9   13
[2,]    2    6   10   14
[3,]    3    7   11   15
[4,]    4    8   12   16
lista1[[2]]
     [,1] [,2]
[1,]    2    7
[2,]    3   11
[3,]    5   13

Es posible, en la fase de creación de una lista, asignar un nombre a cada uno de sus componentes. Si los componentes de una lista tienen un nombre, se puede acceder a ellos, y posteriormente a los elementos que los componen, mediante el símbolo $.

lista2 <- list(comp1 = x, comp2 = y)
lista2
$comp1
     [,1] [,2] [,3] [,4]
[1,]    1    5    9   13
[2,]    2    6   10   14
[3,]    3    7   11   15
[4,]    4    8   12   16

$comp2
     [,1] [,2]
[1,]    2    7
[2,]    3   11
[3,]    5   13
lista2$comp2
     [,1] [,2]
[1,]    2    7
[2,]    3   11
[3,]    5   13
lista2$comp2[3]
[1] 5

Devuelve el valor NULL si no se han asignado. Además de NULL, TRUE y FALSE, R tiene otros valores reservados.

Probablemente, el más relevante es NA, que indica un valor faltante. No es raro encontrar valores NaN (número indefinido) e Inf (infinito).

9.4.4 Filtrado (Subsetting)

La forma más básica de hacer un filtro (subsetting) es extraer un grupo de elementos de un vector, por ejemplo:

mi_vector <- 1:10
mi_vector[3:5]  # extraer elementos 3 a 5
[1] 3 4 5
mi_vector[c(1, 2, 9)]  # extraer ciertos elementos
[1] 1 2 9
new_vector <- mi_vector[3:5]  # asignar valores a un nuevo vector
new_vector
[1] 3 4 5

También se puede usar la función c() para quitar algunos subsets (subsecciones) de la matriz:

mi_matriz[c(1:3, 5), c(2, 4)]
     [,1] [,2]
[1,]    2    4
[2,]    7    9
[3,]    2    4
[4,]    2    4

Nótese la diferencia entre [[]] y [] en las listas:

nueva_lista <- lista1[1]  # devuelve la lista
nuevo_valor <- lista1[[1]]  # devuelve un objeto que estaba en la lista

nueva_lista
[[1]]
     [,1] [,2] [,3] [,4]
[1,]    1    5    9   13
[2,]    2    6   10   14
[3,]    3    7   11   15
[4,]    4    8   12   16
nuevo_valor
     [,1] [,2] [,3] [,4]
[1,]    1    5    9   13
[2,]    2    6   10   14
[3,]    3    7   11   15
[4,]    4    8   12   16

Se debe usar [] para el subset de una lista:

nueva_lista <- lista1[1:2]

9.4.5 Cargar datos en R

Cuando la intención es hacer una investigación utilizando datos secundarios, lo primero que se debe realizar (una vez diseñadas las preguntas de investigación y la/s hipótesis), es seleccionar los datos con los que se desea trabajar. En esta ocasión, se presenta cómo abrir una base de datos en R.

9.4.5.1 Data Frames

Como ejemplo, se construyen algunos datos…

numero_estudiante <- c(1:10)

notas <- c("A", "B", "C", "A", "C", "F", "D", "B", "B", "A")

clase <- c(rep(0, times = 5), rep(1, times = 5))

comida_gratis <- rep(TRUE, times = 10)

Ahora se pueden unir los vectores que se crearon antes para hacer un data frame, que es uno de los tipos de data más comunes en R. Los data.frames sirven para contener muchos tipos de valores (sean textuales o numéricos) y además sus columnas son fáciles de indexar por nombre utilizando el operador $. Es lo más cercano a una base de datos tradicional, con observaciones (filas) y variables (columnas).

Para evitar que las notas (en formato de texto) se conviertan en factores de variables, es decir, que se transformen en una variable categórica de R, se debe implementar el argumento stringsAsFactors = FALSE.

mis_datos <- data.frame(numero_estudiante, notas, clase, comida_gratis, stringsAsFactors = FALSE)

También es posible designar el nombre de las columnas:

colnames(mis_datos) <- c("numero_estudiante", "notas", "clase", "comida_gratis")

Al revisar cómo queda el data.frame:

mis_datos
Tabla 9.1:
numero_estudiantenotasclasecomida_gratis
1A0TRUE
2B0TRUE
3C0TRUE
4A0TRUE
5C0TRUE
6F1TRUE
7D1TRUE
8B1TRUE
9B1TRUE
10A1TRUE

La indexación funciona de la misma manera para las matrices, pero con un pequeño cambio:

mis_datos[, 1]
 [1]  1  2  3  4  5  6  7  8  9 10
mis_datos[2, 4]
[1] TRUE
mis_datos$numero_estudiante  # $ Indexación de columnas
 [1]  1  2  3  4  5  6  7  8  9 10
mis_datos$notas[3]  # Tratar $ Indexación de columnas como vectores
[1] "C"

9.4.5.2 Subsetting inteligente

La función which() permite identificar observaciones que cumplen ciertos criterios, que el usuario dispone. Usando el operador $, se habilita a acceder a una variable del data.frame, según su nombre:

which(mis_datos$notas == "A")
[1]  1  4 10

De esta forma, se puede crear un dataset que sólo incluya a los estudiantes que obtuvieron ‘A’ o ‘B’ como notas, guardando los índices de sus notas, utilizando para extraerlos de los datos totales:

A_estudiantes <- which(mis_datos$notas == "A")
B_estudiantes <- which(mis_datos$notas == "B")
estudiantes_dataset_reducido <- c(A_estudiantes, B_estudiantes)

Luego se selecciona el vector para indexar únicamente algunas filas: para ello, se puede extraerlas y guardarlas como objetos. Nota: si se indexa por [fila, columna] y queda un campo vacío, se toma la fila o columna entera.

datos_reducidos <- mis_datos[estudiantes_dataset_reducido, ]
datos_reducidos
Tabla 9.2:
numero_estudiantenotasclasecomida_gratis
1A0TRUE
4A0TRUE
10A1TRUE
2B0TRUE
8B1TRUE
9B1TRUE

Otra manera sencilla de aplicar un filtro es a través de la función subset():

seleccion_data2 <- subset(mis_datos, notas == "A" | notas == "B")
seleccion_data2
Tabla 9.3:
numero_estudiantenotasclasecomida_gratis
1A0TRUE
2B0TRUE
4A0TRUE
8B1TRUE
9B1TRUE
10A1TRUE

9.4.5.3 Carga de datos en listas

Para crear una lista vacía, se utiliza la función vector():

mi_lista <- vector(mode = "list", length = 10)

También se puede crear una lista a partir de objetos. Cada entrada puede ser llamada una lista, igual que se hace con un data.frame:

mi_lista <- list(num = 10, animal = "vaca", vec = c(1:10), dat = mis_datos)

Otra opción es crear una lista vacía y luego llenarla usando el operador $:

mi_lista <- list()

Una vez creada, se llena de datos:

mi_lista$num <- 10
mi_lista$dat <- mis_datos
mi_lista$cancion_favo <- "Malamente"

Además, se pueden pegar listas al final de otras listas, usando la función append():

mi_lista <- append(mi_lista, list(list(27, 14, "perro")))

Se observa el contenido de la lista:

print(mi_lista)
$num
[1] 10

$dat
   numero_estudiante notas clase comida_gratis
1                  1     A     0          TRUE
2                  2     B     0          TRUE
3                  3     C     0          TRUE
4                  4     A     0          TRUE
5                  5     C     0          TRUE
6                  6     F     1          TRUE
7                  7     D     1          TRUE
8                  8     B     1          TRUE
9                  9     B     1          TRUE
10                10     A     1          TRUE

$cancion_favo
[1] "Malamente"

[[4]]
[[4]][[1]]
[1] 27

[[4]][[2]]
[1] 14

[[4]][[3]]
[1] "perro"

9.4.5.4 Importar datos desde Excel

Existen numerosas fuentes de las que obtener datos secundarios. En la sección anterior, se realizó un breve recorrido sobre datos primarios. Estos últimos, son aquellos que genera el usuario. Por ejemplo, se puede realizar una encuesta y, en base a los resultados obtenidos, generar una base de datos que nos sirva de punto de partida para luego, incurrir en el análisis.

Para ello, se deben seguir los siguientes pasos: utilizar una base de datos como archivo de Excel y moverlo a la carpeta del primer proyecto que se crea en la sesión anterior, para luego incorporarla a la sub-carpeta llamada “datos”.

Un tipo de formato muy conocido es el de Excel, cuyas extensiones pueden ser .xls y .xlsx, siendo la primera más antiüa que la segunda.

El objetivo es visualizar estos datos en la ventana del entorno de RStudio. Para ello, se necesita un paquete que ayude a leer estos datos, el cual se obtiene siguiendo los siguientes pasos:

  1. ingresar a la carpeta del proyecto sobre el que se está trabajando:
  • clicar sobre “primer_proyecto.Rproj” (en lugar del nombre “primer proyecto, hay que insertar el nombre del proyecto en particular, que en este caso, se llama”primer_proyecto”. La extensión del archivo debe ser .Rproj, que es la que tienen todos los proyectos en R).
  1. Ir a la consola y ejecutar el siguiente comando:
install.packages("readxl")

Este paquete permite trabajar con archivos de Excel específicamente. En caso de tener otro tipo de archivo, debe usar la función o paquete indicado.

  1. Abrir la librería del paquete recientemente instalado, ejecutando el siguiente comando, nuevamente en la consola:
library(readxl)

Nótese que para abrir la librería no se precisan comillas entre los paréntesis, a diferencia de durante su instalación (detallada en el paso 2).

  1. Colocar la ruta en donde se encuentra mi base de datos. En este caso, el directorio donde se encuentra mi base de datos es: “/Users/sofiajaime/Documents/rprojects/primer_proyecto/datos/estaciones_tren.xlsx”. Hay que tener en cuenta que esta ruta es específica de cada usuario, en su ordenador local.

Es posible obtener esta ruta/path fácilmente yendo a la carpeta donde este se encuentra, clicando en el botón derecho sobre la misma y en la opción “Propiedades” en el caso de un PC o bien en “Obtener información” o “Get info” si es con iOS.

Luego, simplemente hay que denominar al objeto “encuesta”, en este caso. Seguido, colocar una función read_excel y entre paréntesis y comillas, pegar la ruta propia que dará acceso al archivo seleccionado. La línea de código es la siguiente:

encuesta <- read_excel("bases/estaciones_tren.xls")
  1. Si se han realizado los pasos anteriores correctamente, aparecerá la base de datos en el entorno o environment de RStudio. Allí es posible ver cuántas observaciones y cuántas variables reconoce el programa dentro de la base. Al clicar sobre la misma se abrirá un archivo de R con los datos de la base especificada, que sirve para visualizar de manera más sencilla toda la información que contiene.

Para comprobar que el trabajo se haya realizado bien, se puede “llamar” al objeto “encuesta” de la siguiente manera, mostrando solo los primeros 6 casos:

head(encuesta)
Tabla 9.4:
meslinearamalestacionlatitudlongitud
2018-12-01UrquizaLemosTropezón-3.46e+07-5.86e+07
2018-12-01UrquizaLemosTeniente Agneta-3.45e+05-5.87e+07
2018-12-01UrquizaLemosSargento Cabral-3.45e+07-5.87e+07
2018-12-01UrquizaLemosSargento Barrufaldi-3.46e+07-5.87e+07
2018-12-01UrquizaLemosRubén Darío-3.46e+07-5.86e+07
2018-12-01UrquizaLemosPedro Arata-3.46e+07-5.85e+07

Sobre algunos errores comunes: a veces, se confunden en detalles que, en R, hacen la diferencia. Algunos comunes son:

  • Seleccionar las barras incorrectas (/ ó ) según la computadora: en la ruta que da acceso a los documentos que se quieren utilizar, hay muchas barras. Es necesario colocar las correctas según la computadora en la que se esté trabajando, y además, que todas ellas estén en la misma dirección. Si se utilizan estas barras: /, deben estas todas en la misma dirección en la línea de código que se esté escribiendo, porque si hay inconsistencias (utilizando ambas de manera mezclada) R no podrá leer el archivo deseado.

  • Ruta errónea: se debe comprobar que cada ruta es fácil de encontrar, tal como se especifica en el paso 4 que se encuentra más arriba.

  • Símbolos incorrectos, excedentes o faltantes: un símbolo de más o uno ausente pueden hacer que R no entienda lo que se le “ordena”. Por ello, verificar que todos los símbolos estén correctamente escritos, en el lugar que deben estar, es muy importante.