Maestría en Hidrología
Universidad de Cuenca
http://www.ucuenca.edu.ec/maestria-ecohidrologia/

Johanna Orellana-Alvear (MSc, PhD candidate)
johanna.orellana@ucuenca.edu.ec

Curso completo en: http://rpubs.com/Johanna_Orellana_Alvear/programacion_r_indice_2018



En esta lección aprenderás a:
- Leer y escribir archivos de texto
- Guardar las variables actuales del entorno de trabajo
- Recuperar elementos específicos de objetos R
- Modificar el valor asociado a elementos en R
- Cómo generar test lógicos
- Utilizar la función subset

Temario

A- Help
B- Lectura y escritura de archivos de texto
C- Guardar el entorno de trabajo
D- Indexación
E- Modificación de valores
F- Subconjuntos lógicos
G- Función subset

Help

Para acceder a las opciones de ayuda HELP

    ?sqrt
    ?log10
    ?sample

Lectura y escritura de archivos de texto

Recapitulemos el uso de las funciones getwd() y setwd(). El primero obtiene la ruta del directorio actual de trabajo, en tanto que el segundo especifica o cambia la ruta del directorio sobre el cual se desea trabajar. Ahora vamos a ubicarnos en el directorio que contiene el archivo de texto que deseamos abrir en R (cargar en la memoria).

getwd()
## [1] "/Users/johannaorellana/Documents/R_Workspace/Maestria_Hidrologia_2018"
setwd("~/Documents/R_WORKSPACE/Maestria_Hidrologia_2018")
df.observaciones <- read.table("observaciones_2003.csv", header = TRUE)
head(df.observaciones)
##           FECHA VALOR STATUS ESTACION year day month
## 7671 01/01/2003     0            M012 2003   1     1
## 7672 02/01/2003     0            M012 2003   2     1
## 7673 03/01/2003     0            M012 2003   3     1
## 7674 04/01/2003     0            M012 2003   4     1
## 7675 05/01/2003     0            M012 2003   5     1
## 7676 06/01/2003     0            M012 2003   6     1

¿Qué sucede con los valores de la columna STATUS?

De ser necesario es posible indicarle a R como se desea manejar los valores nulos (donde no existen datos). En ocasiones inclusive nuestro archivo de texto podría usar un caracter especial de su fuente inicial para representar estos datos (e.g la palabra NULL). En este caso se incrementa un argumento a la función read.table.

df.observaciones <- read.table("observaciones_2003.csv", header = TRUE, na.strings = "", stringsAsFactors = FALSE)

df.observaciones <- read.table("observaciones_2003.csv", header = TRUE, stringsAsFactors = FALSE)

head(df.observaciones)
##           FECHA VALOR STATUS ESTACION year day month
## 7671 01/01/2003     0            M012 2003   1     1
## 7672 02/01/2003     0            M012 2003   2     1
## 7673 03/01/2003     0            M012 2003   3     1
## 7674 04/01/2003     0            M012 2003   4     1
## 7675 05/01/2003     0            M012 2003   5     1
## 7676 06/01/2003     0            M012 2003   6     1
class(df.observaciones)
## [1] "data.frame"
nrow(df.observaciones)
## [1] 8030

Existen otros argumentos para leer un archivo y también otras funciones.

df.observaciones.sep <- read.table("observaciones_2003.csv", sep = ",", header = TRUE, skip = 3, nrow = 5)
df.observaciones.csv <- read.csv("observaciones_2003.csv")

Así como es posible leer un archivo y cargarlo en R como un data frame, es posible hacer lo opuesto; almacenando un data frame en un archivo de texto.

write.csv(df.observaciones, "df.observaciones.csv", row.names = FALSE)
write.table(df.observaciones, "dataFrame_observaciones.txt", row.names = FALSE)

Guardar el entorno de trabajo

Almacenar las variables del espacio de trabajo actual en un archivo de extensión .RData. Esto permite guardar el estado actual de mis variables cuando por ejemplo ellas son el resultado de varias horas de procesamiento. No sería óptimo ejecutar un programa cada vez en espera de obtener la actualización de ciertas variables.

a<-1
b<-2
c<-3
save(a, b, file = "variables_parciales.RData") 

En el caso de salvar todas las variables del espacio de trabajo

save(list = ls(all = TRUE),file = "todas_variables.RData") 

Ahora que ya tengo un archivo .RData con mis variables de interés, puedo cargar este archivo nuevamente. Por ejemplo, al día siguiente luego de que apague el computador y perdí toda mi información de trabajo.

load("todas_variables.RData")

Indexación

(Método básico) – Cómo acceder a ciertos datos de los objetos de R

Para acceder a uno o varios elementos de un data frame, se colocan los índices de fila(s) y columna(s) deseados entre corchetes, así [filas,columnas]. El primer índice se utilizará para recuperar las filas del data frame y el segundo para recuperar las columnas.

Existen 5 maneras diferentes (las más utilizadas) de escribir los índices en R.

  • Enteros Positivos
  • Enteros Negativos
  • Espacios en blanco
  • Valores lógicos
  • Nombres
Enteros Positivos

La analogía es la notación algebraica de i,j: df.observaciones[i,j].

head(df.observaciones)
##           FECHA VALOR STATUS ESTACION year day month
## 7671 01/01/2003     0            M012 2003   1     1
## 7672 02/01/2003     0            M012 2003   2     1
## 7673 03/01/2003     0            M012 2003   3     1
## 7674 04/01/2003     0            M012 2003   4     1
## 7675 05/01/2003     0            M012 2003   5     1
## 7676 06/01/2003     0            M012 2003   6     1
df.observaciones[1, 1]
## [1] "01/01/2003"

Para extraer más de un valor, se debe usar un vector de enteros positivos. Por ejemplo para recuperar la primera fila de nuestro data frame de observaciones.

df.observaciones[1,c(1,2,3,4,5,6,7)]
##           FECHA VALOR STATUS ESTACION year day month
## 7671 01/01/2003     0            M012 2003   1     1
df.observaciones[1,1:7]
##           FECHA VALOR STATUS ESTACION year day month
## 7671 01/01/2003     0            M012 2003   1     1

Si el objetivo es trabajar posteriormente con este subconjunto de datos, al asignar a una nueva variable en realidad obtenemos una copia de la primera fila del data frame.

new <- df.observaciones[1, 1:7]
new
##           FECHA VALOR STATUS ESTACION year day month
## 7671 01/01/2003     0            M012 2003   1     1

La misma sintaxis es válida para cualquier objeto R en tanto que se utilice la dimensión adecuada. Por ejemplo un vector posee una sola dimensión por lo tanto requiere un sólo índice. La numeración de índices en R empieza en 1

vec<-c(6,1,3,6,10,5) 
vec[1:3]
## [1] 6 1 3

¿Qué pasa al seleccionar dos o más columnas de un data frame o cuándo seleccionamos solo una columna?

En caso de que se requiera como salida un data frame para el segundo caso basta con agregar el argumento drop

df.observaciones[1:2, 1, drop = FALSE]
##           FECHA
## 7671 01/01/2003
## 7672 02/01/2003
Enteros Negativos

Es el caso opuesto de la indexación con enteros positivos. R retornará todos los elementos a excepción de los elementos que pertenecen a índice negativo. Esta es una forma más eficiente de obtener subconjuntos de datos para el caso de que se desee conservar la mayor cantidad de filas o columnas.

df.observaciones[-(2:52), 1:3]
Espacios en blanco

Se puede utilizar un espacio en blanco para indicarle a R que debe extraer todos los valores en una dimensión. Esto es útil para recuperar/extraer todas las columnas o todas las filas de un data frame.

df.observaciones[1, ]
##           FECHA VALOR STATUS ESTACION year day month
## 7671 01/01/2003     0            M012 2003   1     1
Valores lógicos

Si se provee un vector de valores TRUEs y FALSEs como índices, R asociará cada valor TRUE o FALSE a la fila (o columna) correspondiente del data frame. Todas las filas o columnas que estén asociadas al valor TRUE se extraerán. Para que este método funcione, el vector booleano debe tener la misma longitud que la dimensión que se desea obtener el subconjunto de datos.

df.observaciones[1, c(TRUE, TRUE, FALSE,FALSE,TRUE,FALSE,TRUE)]
##           FECHA VALOR year month
## 7671 01/01/2003     0 2003     1

Hacer el ejercicio con las columnas es posible pero…. y con las filas?. Debería asegurar la creación de un vector booleano de la misma longitud que el total de filas del data frame. Entonces la pregunta es…cómo obtener un vector booleano del tamaño de filas del data frame? La sección de subconjuntos lógicos aborda este tema aquí

Nombres

Finalmente es posible extraer/recuperar un subconjunto de datos a partir del nombre de las columas.

df.observaciones[, c("FECHA","ESTACION")]

Otro método de indexación:Signos de dólares

Se puede extraer toda la columna de un data frame utilizando el signo de dólares como el separador entre el nombre del data frame y el nombre de la columna(variable) de interés. R retornará un vector. Esta acción es útil cuando queremos por ejemplo evaluar la media de esta variable. Tomemos en cuenta que la función mean(x), espera que x sea un VECTOR.

df.observaciones$VALOR
mean(df.observaciones$VALOR)

Modificación de valores – ¿Cómo puedo modificar/reasignar un valor?

vec<-c(0,0,0,0,0,0) 
vec
## [1] 0 0 0 0 0 0
vec[1]
## [1] 0
vec[1] <- 1000
vec
## [1] 1000    0    0    0    0    0

También se puede reemplazar múltiples valores en el vector en tanto que los nuevos valores sean iguales en número a los valores seleccionados.

vec[c(1, 3, 5)] <- c(1, 1, 1) 
vec
## [1] 1 0 1 0 1 0

¿Y qué hay de crear nuevos valores en un objeto? R permite crear un nuevo elemento, en el caso de un vector o incluso una nueva columna(variable) en el caso de un data frame; expandiendo la longitud del objeto.

vec[7] <- 0
vec
## [1] 1 0 1 0 1 0 0
filas <- nrow(df.observaciones)
df.observaciones$new <- 1:filas
head(df.observaciones)
##           FECHA VALOR STATUS ESTACION year day month new
## 7671 01/01/2003     0            M012 2003   1     1   1
## 7672 02/01/2003     0            M012 2003   2     1   2
## 7673 03/01/2003     0            M012 2003   3     1   3
## 7674 04/01/2003     0            M012 2003   4     1   4
## 7675 05/01/2003     0            M012 2003   5     1   5
## 7676 06/01/2003     0            M012 2003   6     1   6

En el caso opuesto, para eliminar o remover una columna de un data framese usa la expresión df.observaciones$new <- NULL

Subconjuntos lógicos

Previamente identificamos la posibilidad de obtener un subconjunto de datos a partir de un índice de vector booleano.

vec
## [1] 1 0 1 0 1 0 0
vec[c(FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE)]
## [1] 1

No es necesario que nosotros creemos el vector booleano, podemos efectuar un test lógico para obtener esta estructura. Existen 7 operadores lógicos para realizar comparaciones.

  • a>b
  • a>=b
  • a<b
  • a<=b
  • a==b
  • a!=b
  • a %in% c(a, b, c)
1>2
## [1] FALSE
1>c(0,1,2)
## [1]  TRUE FALSE FALSE
c(1,2,3)==c(3,2,1)
## [1] FALSE  TRUE FALSE

El único caso particular que no efectúa comparación elemento a elemento es %in%.

1 %in% c(3, 4, 5)
## [1] FALSE
c(1, 2) %in% c(3, 4, 5)
## [1] FALSE FALSE
c(1, 2, 3) %in% c(3, 4, 5)
## [1] FALSE FALSE  TRUE
c(1, 2, 3, 4) %in% c(3, 4, 5)
## [1] FALSE FALSE  TRUE  TRUE

Modificar valores a partir de una expresión de vector booleano.

df.observaciones$ESTACION == "M012"
df.observaciones$VALOR[df.observaciones$ESTACION == "M012"]
df.observaciones$VALOR[df.observaciones$ESTACION == "M012"] <- 10

Función subset

Existe una función que se utiliza para obtener un subonjunto de datos, esta se denomina subset. De acuerdo al siguiente ejemplo, cuáles son los argumentos que se deducen que requiere esta función?.

newdata <- subset(df.observaciones, month >= 6 | month < 3, select=c(FECHA,ESTACION,month))
newdata