From 1f98c6bee3aafa5ad90af892b0907db5e0738835 Mon Sep 17 00:00:00 2001 From: juli arancio Date: Sat, 24 Feb 2018 15:10:22 -0300 Subject: [PATCH] Update 04-data-structures-part1.Rmd cambio md a Rmd --- episodes/04-data-structures-part1.Rmd | 1157 +++---------------------- 1 file changed, 144 insertions(+), 1013 deletions(-) diff --git a/episodes/04-data-structures-part1.Rmd b/episodes/04-data-structures-part1.Rmd index 379aff50..17ffb6a0 100644 --- a/episodes/04-data-structures-part1.Rmd +++ b/episodes/04-data-structures-part1.Rmd @@ -17,19 +17,30 @@ keypoints: source: Rmd --- +```{r, include=FALSE} +source("../bin/chunk-options.R") +knitr_fig_path("04-") + +## Save the data +cats_orig <- data.frame(coat = factor(c("calico", "black", "tabby")), + weight = c(2.1, 5.0, 3.2), + likes_string = c(1, 0, 1)) +cats_bad <- data.frame(coat = factor(c("calico", "black", "tabby", "tabby")), + weight = factor(c(2.1, 5.0, 3.2, '2.3 or 2.4')), + likes_string = c(1, 0, 1, 1)) +cats <- cats_orig +``` Una de las características más poderosas de R es su habilidad de manejar datos tabulares - como los que puedes tener en una planilla de cálculo o un archivo CSV. Comencemos creando un **dataset** de ejemplo en tu directorio `datos/`, en el archivo llamado `feline-data.csv`: - -~~~ +```{r, eval=FALSE} coat,weight,likes_string calico,2.1,1 black,5.0,0 tabby,3.2,1 -~~~ -{: .r} +``` > ## Consejo: Edición de archivos de texto en R > @@ -37,26 +48,19 @@ tabby,3.2,1 > o en RStudio usando el ítem del Menú **File -> New File -> Text File**. {: .callout} - +```{r, echo = FALSE} +cats.df <- data.frame(coat = c("calico", "black", "tabby"), + weight = c(2.1, 5.0, 3.2), + likes_string = c(1, 0, 1)) +write.csv(cats.df, "data/feline-data.csv", row.names = FALSE) +``` Podemos leer el archivo en R con el siguiente comando: -~~~ +```{r} cats <- read.csv(file = "data/feline-data.csv") cats -~~~ -{: .r} - - - -~~~ - coat weight likes_string -1 calico 2.1 1 -2 black 5.0 0 -3 tabby 3.2 1 -~~~ -{: .output} - +``` La función `read.table` se usa para leer datos tabulares que están guardados en un archivo de texto, donde las columnas de datos están separadas por un signo de puntuación como en los archivos CSV (donde **csv** es **comma-separated values** en inglés, es decir, valores separados por comas). @@ -70,89 +74,25 @@ por tabuladores. De las tres variantes, `read.csv` es la usada más comúnmente. Podemos empezar a explorar el **dataset** inmediatamente, proyectando las columnas usando el operador `$`: - -~~~ +```{r} cats$weight -~~~ -{: .r} - - - -~~~ -[1] 2.1 5.0 3.2 -~~~ -{: .output} - - - -~~~ cats$coat -~~~ -{: .r} - - - -~~~ -[1] calico black tabby -Levels: black calico tabby -~~~ -{: .output} - - +``` Podemos efectuar otras operaciones a las columnas: -~~~ -## Considera que descubrimos que la balanza pesa dos kilos menos: +```{r} +## Say we discovered that the scale weighs two Kg light: cats$weight + 2 -~~~ -{: .r} - - -~~~ -[1] 4.1 7.0 5.2 -~~~ -{: .output} - - - -~~~ paste("My cat is", cats$coat) -~~~ -{: .r} - - - -~~~ -[1] "My cat is calico" "My cat is black" "My cat is tabby" -~~~ -{: .output} +``` Pero qué pasa con: - -~~~ +```{r} cats$weight + cats$coat -~~~ -{: .r} - - - -~~~ -Warning in Ops.factor(cats$weight, cats$coat): '+' not meaningful for -factors -~~~ -{: .error} - - - -~~~ -[1] NA NA NA -~~~ -{: .output} - - +``` Entender qué es lo que pasa en este case es clave para analizar datos en R exitosamente. @@ -162,90 +102,19 @@ Si adivinaste que el último comando iba a resultar en un error porque `2.1` má `"black"` no tiene sentido, estás en lo cierto - y ya tienes alguna intuición sobre un concepto importante en programación que se llama *tipos de datos*. Podemos preguntar cuál es el tipo de datos de algo: - -~~~ -typeof(gatos$peso) -~~~ -{: .r} - - - -~~~ -[1] "double" -~~~ -{: .output} +```{r} +typeof(cats$weight) +``` Hay 5 tipos de datos principales: `double`, `integer`, `complex`, `logical` and `character`. - -~~~ +```{r} typeof(3.14) -~~~ -{: .r} - - - -~~~ -[1] "double" -~~~ -{: .output} - - - -~~~ -typeof(1L) # El sufijo L forza a que el número sea un entero, ya que R por defecto usa números flotantes -~~~ -{: .r} - - - -~~~ -[1] "integer" -~~~ -{: .output} - - - -~~~ +typeof(1L) # The L suffix forces the number to be an integer, since by default R uses float numbers typeof(1+1i) -~~~ -{: .r} - - - -~~~ -[1] "complex" -~~~ -{: .output} - - - -~~~ typeof(TRUE) -~~~ -{: .r} - - - -~~~ -[1] "logical" -~~~ -{: .output} - - - -~~~ typeof('banana') -~~~ -{: .r} - - - -~~~ -[1] "character" -~~~ -{: .output} - +``` No importa cuan complicado sea nuestro análisis, todos los datos en R se interpretan con uno de estos tipos de datos básicos. Este rigor tiene algunas consecuencias importantes. @@ -253,60 +122,33 @@ Un usuario ha agregado detalles de otro gato. Esta información está en el arch `datos/datos-felinos_v2.csv`. - -~~~ +```{r, eval=FALSE} file.show("data/feline-data_v2.csv") -~~~ -{: .r} - +``` -~~~ +```{r, eval=FALSE} coat,weight,likes_string calico,2.1,1 black,5.0,0 tabby,3.2,1 tabby,2.3 or 2.4,1 -~~~ -{: .r} +``` + Carga los datos de los nuevos gatos de la misma forma anterior, y comprueba qué tipos de datos encuentras en la columna `weight`: -~~~ +```{r} cats <- read.csv(file="data/feline-data_v2.csv") typeof(cats$weight) -~~~ -{: .r} - - - -~~~ -[1] "integer" -~~~ -{: .output} +``` Oh no, nuestros pesos ya no son de tipo **double**! Si intentamos hacer los mismos cálculos anteriores, tenemos problemas: -~~~ +```{r} cats$weight + 2 -~~~ -{: .r} - - - -~~~ -Warning in Ops.factor(cats$weight, 2): '+' not meaningful for factors -~~~ -{: .error} - - - -~~~ -[1] NA NA NA NA -~~~ -{: .output} - +``` ¿Qué ocurrió? Cuando R lee un archivo CSV en una de estas tablas, insiste que todas las columnas sean del mismo tipo de datos básico; si no puede entender @@ -317,19 +159,9 @@ se interpreta como **double**. La tabla que R cargó con los datos de los gatos Podemos ver que es un **data.frame** si usamos la función `class`: - -~~~ +```{r} class(cats) -~~~ -{: .r} - - - -~~~ -[1] "data.frame" -~~~ -{: .output} - +``` Para usar nuestros datos en R exitosamente, necesitamos entender cuáles son las estructuras de datos básicas, y cómo se comportan. Por ahora, eliminemos la línea extra de los datos sobre gatos y volvamos @@ -347,63 +179,38 @@ tabby,3.2,1 Y en RStudio: - -~~~ +```{r, eval=FALSE} cats <- read.csv(file="data/feline-data.csv") -~~~ -{: .r} +``` +```{r, include=FALSE} +cats <- cats_orig +``` ## Vectores y Coerción de Tipos Para entender mejor este comportamiento, veamos otra de las estructuras de datos en R: el **vector**. -~~~ +```{r} my_vector <- vector(length = 3) my_vector -~~~ -{: .r} - - - -~~~ -[1] FALSE FALSE FALSE -~~~ -{: .output} - +``` Un vector en R es esencialmente una lista ordenada de cosas, con la condición especial de que *todos* los elementos en un vector tienen que ser del mismo tipo de datos básico*. Si no eliges un tipo de datos, por defecto R elige el tipo de datos **logical**. También puedes declarar un vector vacío de cualquier tipo que quieras. -~~~ +```{r} another_vector <- vector(mode='character', length=3) another_vector -~~~ -{: .r} - - - -~~~ -[1] "" "" "" -~~~ -{: .output} +``` Puedes checar si algo es un vector: -~~~ +```{r} str(another_vector) -~~~ -{: .r} - - - -~~~ - chr [1:3] "" "" "" -~~~ -{: .output} - +``` La salida algo críptica de este comando indica el tipo de datos básico encontrado en este vector -en este caso `chr` o **character**; una indicación del número de elementos en el vector - específicamente los índices @@ -412,18 +219,9 @@ de los elementos del vector - en este caso **strings** vacíos. Si, en forma similar, hacemos: - -~~~ +```{r} str(cats$weight) -~~~ -{: .r} - - - -~~~ - num [1:3] 2.1 5 3.2 -~~~ -{: .output} +``` podemos ver que `cats$weight` también es un vector - *las columnas de datos que cargamos en **data.frames** de R son todas vectores* y este es el motivo por el cuál R requiere @@ -449,108 +247,41 @@ que todas las columnas sean del mismo tipo de datos básico. También puedes crear vectores con contenido explícito con la función **combine**: -~~~ + +```{r} combine_vector <- c(2,6,3) combine_vector -~~~ -{: .r} - - - -~~~ -[1] 2 6 3 -~~~ -{: .output} - +``` Dado lo que aprendimos hasta ahora, ¿qué piensas que va a producir el siguiente código? - -~~~ +```{r} quiz_vector <- c(2,6,'3') -~~~ -{: .r} +``` Esto se denomina *coerción de tipos de datos* y es motivo de muchas sorpresas y la razón por la cual es necesario conocer los tipos de datos básicos y cómo R los interpreta. Cuando R encuentra una mezcla de tipos de datos (en este caso númerico y caracteres) para combinarlos en un vector, va a forzarlos a ser del mismo tipo. Considera: - -~~~ +```{r} coercion_vector <- c('a', TRUE) coercion_vector -~~~ -{: .r} - - - -~~~ -[1] "a" "TRUE" -~~~ -{: .output} - - - -~~~ another_coercion_vector <- c(0, TRUE) another_coercion_vector -~~~ -{: .r} - - - -~~~ -[1] 0 1 -~~~ -{: .output} +``` Las reglas de coerción son: `logical` -> `integer` -> `numeric` -> `complex` -> `character`, donde -> se puede leer como *se transforma en*. Puedes intentar forzar la coerción de acuerdo a esta cadena usando las funciones `as.`: - -~~~ +```{r} character_vector_example <- c('0','2','4') character_vector_example -~~~ -{: .r} - - - -~~~ -[1] "0" "2" "4" -~~~ -{: .output} - - - -~~~ character_coerced_to_numeric <- as.numeric(character_vector_example) character_coerced_to_numeric -~~~ -{: .r} - - - -~~~ -[1] 0 2 4 -~~~ -{: .output} - - - -~~~ numeric_coerced_to_logical <- as.logical(character_coerced_to_numeric) numeric_coerced_to_logical -~~~ -{: .r} - - - -~~~ -[1] FALSE TRUE TRUE -~~~ -{: .output} +``` Como puedes ver, algunas cosas sorprendentes ocurren cuando R forza un tipo de datos en otro tipo! Dejando de lado los detalles de la coerción, la cuestión es: si tus datos no lucen como pensabas que @@ -564,219 +295,51 @@ Pero la coerción de tipos también puede ser muy útil. Por ejemplo, en los dat lo que nuestros datos representan. Podemos convertir esta columna al tipo de datos **`logical`** usando la función `as.logical`: - -~~~ +```{r} cats$likes_string -~~~ -{: .r} - - - -~~~ -[1] 1 0 1 -~~~ -{: .output} - - - -~~~ cats$likes_string <- as.logical(cats$likes_string) cats$likes_string -~~~ -{: .r} - - - -~~~ -[1] TRUE FALSE TRUE -~~~ -{: .output} +``` La función **combine**, `c()`, también agregará elementos al final de un vector existente: - -~~~ +```{r} ab_vector <- c('a', 'b') ab_vector -~~~ -{: .r} - - - -~~~ -[1] "a" "b" -~~~ -{: .output} - - - -~~~ combine_example <- c(ab_vector, 'SWC') combine_example -~~~ -{: .r} - - - -~~~ -[1] "a" "b" "SWC" -~~~ -{: .output} - - +``` También puedes hacer una serie de números: - -~~~ +```{r} mySeries <- 1:10 mySeries -~~~ -{: .r} - - - -~~~ - [1] 1 2 3 4 5 6 7 8 9 10 -~~~ -{: .output} - - - -~~~ seq(10) -~~~ -{: .r} - - - -~~~ - [1] 1 2 3 4 5 6 7 8 9 10 -~~~ -{: .output} - - - -~~~ seq(1,10, by=0.1) -~~~ -{: .r} - - - -~~~ - [1] 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 2.1 2.2 2.3 -[15] 2.4 2.5 2.6 2.7 2.8 2.9 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 -[29] 3.8 3.9 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 5.0 5.1 -[43] 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.0 6.1 6.2 6.3 6.4 6.5 -[57] 6.6 6.7 6.8 6.9 7.0 7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 -[71] 8.0 8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 9.0 9.1 9.2 9.3 -[85] 9.4 9.5 9.6 9.7 9.8 9.9 10.0 -~~~ -{: .output} +``` Podemos preguntar algunas cosas sobre los vectores: - -~~~ +```{r} sequence_example <- seq(10) head(sequence_example, n=2) -~~~ -{: .r} - - - -~~~ -[1] 1 2 -~~~ -{: .output} - - - -~~~ tail(sequence_example, n=4) -~~~ -{: .r} - - - -~~~ -[1] 7 8 9 10 -~~~ -{: .output} - - - -~~~ length(sequence_example) -~~~ -{: .r} - - - -~~~ -[1] 10 -~~~ -{: .output} - - - -~~~ class(sequence_example) -~~~ -{: .r} - - - -~~~ -[1] "integer" -~~~ -{: .output} - - - -~~~ typeof(sequence_example) -~~~ -{: .r} - - +``` -~~~ -[1] "integer" -~~~ -{: .output} Finalmente, puedes darle nombres a los elementos de tu vector: - -~~~ +```{r} my_example <- 5:8 names(my_example) <- c("a", "b", "c", "d") my_example -~~~ -{: .r} - - - -~~~ -a b c d -5 6 7 8 -~~~ -{: .output} - - - -~~~ names(my_example) -~~~ -{: .r} - +``` -~~~ -[1] "a" "b" "c" "d" -~~~ -{: .output} > ## Desafío 1 > @@ -787,63 +350,30 @@ names(my_example) > > ## Solución del desafío 1 > > > > -> > ~~~ +> > ```{r} > > x <- 1:26 > > x <- x * 2 > > names(x) <- LETTERS -> > ~~~ -> > {: .r} +> > ``` > {: .solution} {: .challenge} + ## Data Frames Ya mencionamos que las columnas en los **data.frames** son vectores: - -~~~ +```{r} str(cats$weight) -~~~ -{: .r} - - - -~~~ - num [1:3] 2.1 5 3.2 -~~~ -{: .output} - - - -~~~ str(cats$likes_string) -~~~ -{: .r} - - - -~~~ - logi [1:3] TRUE FALSE TRUE -~~~ -{: .output} +``` Esto tiene sentido, pero qué pasa con: - -~~~ +```{r} str(cats$coat) -~~~ -{: .r} - - - -~~~ - Factor w/ 3 levels "black","calico",..: 2 1 3 -~~~ -{: .output} - - +``` ## Factores @@ -852,96 +382,31 @@ parecen caracteres, pero se usan para representar información categórica. Por construyamos un vector de **strings** con etiquetas para las coloraciones para todos los gatos en nuestro estudio: - -~~~ +```{r} coats <- c('tabby', 'tortoiseshell', 'tortoiseshell', 'black', 'tabby') coats -~~~ -{: .r} - - - -~~~ -[1] "tabby" "tortoiseshell" "tortoiseshell" "black" -[5] "tabby" -~~~ -{: .output} - - - -~~~ str(coats) -~~~ -{: .r} - - +``` -~~~ - chr [1:5] "tabby" "tortoiseshell" "tortoiseshell" "black" "tabby" -~~~ -{: .output} Podemos convertir un vector en un **factor** de la siguiente manera: - -~~~ +```{r} CATegories <- factor(coats) class(CATegories) -~~~ -{: .r} - - - -~~~ -[1] "factor" -~~~ -{: .output} - - - -~~~ str(CATegories) -~~~ -{: .r} - - +``` -~~~ - Factor w/ 3 levels "black","tabby",..: 2 3 3 1 2 -~~~ -{: .output} Ahora R puede interpretar que hay tres posibles categorías en nuestros datos - pero también hizo algo sorprendente; en lugar de imprimir los **strings** como se las dimos, imprimió una serie de números. R ha reemplazado las categorías con índices numéricos, lo cuál es necesario porque muchos cálculos estadísticos usan esa representación para datos categóricos: - -~~~ +```{r} typeof(coats) -~~~ -{: .r} - - - -~~~ -[1] "character" -~~~ -{: .output} - - - -~~~ typeof(CATegories) -~~~ -{: .r} - - - -~~~ -[1] "integer" -~~~ -{: .output} +``` > ## Desafío 2 > @@ -954,22 +419,17 @@ typeof(CATegories) > > > > Una solución es usar el argumento `stringAsFactors`: > > -> > -> > ~~~ -> > cats <- read.csv(file="datos/datos-felinos.csv", stringsAsFactors=FALSE) +> > ```{r, eval = FALSE} +> > cats <- read.csv(file="data/feline-data.csv", stringsAsFactors=FALSE) > > str(cats$coat) -> > ~~~ -> > {: .r} -> > +> > ``` > > Otra solución es usar el argumento `colClasses` > > que permiten un control más fino. > > -> > -> > ~~~ -> > cats <- read.csv(file="datos/datos-felinos.csv", colClasses=c(NA, NA, "character")) +> > ```{r, eval = FALSE} +> > cats <- read.csv(file="data/feline-data.csv", colClasses=c(NA, NA, "character")) > > str(cats$coat) -> > ~~~ -> > {: .r} +> > ``` > > > > Nota: Los nuevos estudiantes encuentran los archivos de ayuda difíciles de entender; asegúrese de hacerles saber > > que esto es normal, y anímelos a que tomen su mejor opción en función del significado semantico, @@ -981,22 +441,11 @@ En las funciones de modelado, es importante saber cuáles son los niveles de ref que es el primer factor, pero por defecto los factores están etiquetados en orden alfabetico. Puedes cambiar esto especificando los niveles: - - -~~~ +```{r} mydata <- c("case", "control", "control", "case") factor_ordering_example <- factor(mydata, levels = c("control", "case")) str(factor_ordering_example) -~~~ -{: .r} - - - -~~~ - Factor w/ 2 levels "control","case": 2 1 1 2 -~~~ -{: .output} - +``` En este caso, le hemos dicho explícitamente a R que "control" debería estar representado por 1, y "case" por 2. Esta designación puede ser muy importante para interpretar los @@ -1004,72 +453,24 @@ resultados de modelos estadísticos! ## Listas - Otra estructura de datos que quedrás en tu bolsa de trucos es `list`. Una lista es más simple, en algunos aspectos que los otros tipos, porque puedes poner cualquier cosa que tú quieras en ella: -~~~ +```{r} list_example <- list(1, "a", TRUE, 1+4i) list_example -~~~ -{: .r} - - - -~~~ -[[1]] -[1] 1 - -[[2]] -[1] "a" - -[[3]] -[1] TRUE - -[[4]] -[1] 1+4i -~~~ -{: .output} - - - -~~~ another_list <- list(title = "Numbers", numbers = 1:10, data = TRUE ) another_list -~~~ -{: .r} - - - -~~~ -$title -[1] "Numbers" - -$numbers - [1] 1 2 3 4 5 6 7 8 9 10 - -$data -[1] TRUE -~~~ -{: .output} - +``` Ahora podemos entender algo un poco sorprendente en nuestro **data.frame**; ¿Qué pasa si corremos? -~~~ -typeof(cats) -~~~ -{: .r} - - - -~~~ -[1] "list" -~~~ -{: .output} +```{r} +typeof(cats) +``` Vemos que los **data.frames** parecen listas 'en su cara oculta' - ​​esto es porque un **data.frame** es realmente una lista de vectores y factores, como debe ser - @@ -1079,112 +480,25 @@ columnas juntas en una tabla. En otras palabras, un `data.frame` es una lista especial en la que todos los vectores deben tener la misma longitud. -En nuestro ejemplo de `cats ', tenemos un número entero, un doble y una variable lógica. Como +En nuestro ejemplo de `cats`, tenemos un número entero, un doble y una variable lógica. Como ya hemos visto, cada columna del **data.frame** es un vector. -~~~ -cats$coat -~~~ -{: .r} - - - -~~~ -[1] calico black tabby -Levels: black calico tabby -~~~ -{: .output} - - -~~~ +```{r} +cats$coat cats[,1] -~~~ -{: .r} - - - -~~~ -[1] calico black tabby -Levels: black calico tabby -~~~ -{: .output} - - - -~~~ typeof(cats[,1]) -~~~ -{: .r} - - - -~~~ -[1] "integer" -~~~ -{: .output} - - - -~~~ str(cats[,1]) -~~~ -{: .r} - - - -~~~ - Factor w/ 3 levels "black","calico",..: 2 1 3 -~~~ -{: .output} - +``` Cada fila es una *observación* de diferentes variables del mismo **data.frame**, y por lo tanto puede estar compuesto de elementos de diferentes tipos. -~~~ +```{r} cats[1,] -~~~ -{: .r} - - - -~~~ - coat weight likes_string -1 calico 2.1 TRUE -~~~ -{: .output} - - - -~~~ typeof(cats[1,]) -~~~ -{: .r} - - - -~~~ -[1] "list" -~~~ -{: .output} - - - -~~~ str(cats[1,]) -~~~ -{: .r} - - - -~~~ -'data.frame': 1 obs. of 3 variables: - $ coat : Factor w/ 3 levels "black","calico",..: 2 - $ weight : num 2.1 - $ likes_string: logi TRUE -~~~ -{: .output} +``` > ## Desafío 3 > @@ -1204,118 +518,42 @@ str(cats[1,]) > > > ## Solución al desafío 3 > > -> > ~~~ +> > ```{r, eval=TRUE, echo=TRUE} > > cats[1] -> > ~~~ -> > {: .r} -> > -> > -> > -> > ~~~ -> > coat -> > 1 calico -> > 2 black -> > 3 tabby -> > ~~~ -> > {: .output} +> > ``` > > Podemos interpretar un **data frame** como una lista de vectores. Un único par de corchetes `[1]` > resulta en la primer proyección de la lista, como otra lista. En este caso es la primer columna del > **data frame**. -> > -> > ~~~ +> > ```{r, eval=TRUE, echo=TRUE} > > cats[[1]] -> > ~~~ -> > {: .r} -> > -> > -> > -> > ~~~ -> > [1] calico black tabby -> > Levels: black calico tabby -> > ~~~ -> > {: .output} +> > ``` > > El doble corchete `[[1]]` devuelve el contenido del elemento de la lista. En este caso, > > es el contenido de la primera columna, un _vector_ de tipo _factor_. -> > -> > ~~~ +> > ```{r, eval=TRUE, echo=TRUE} > > cats$coat -> > ~~~ -> > {: .r} -> > -> > -> > -> > ~~~ -> > [1] calico black tabby -> > Levels: black calico tabby -> > ~~~ -> > {: .output} +> > ``` > > Este ejemplo usa el caracter `$` para direccionar elementos por nombre. _coat_ es la > > primer columna del marco de datos, de nuevo un _vector_ de tipo _factor_. -> > -> > -> > ~~~ +> > ```{r, eval=TRUE, echo=TRUE} > > cats["coat"] -> > ~~~ -> > {: .r} -> > -> > -> > -> > ~~~ -> > coat -> > 1 calico -> > 2 black -> > 3 tabby -> > ~~~ -> > {: .output} -> > Aquí estamos usando un solo corchete `[" coat "]` reemplazando el número del índice con +> > ``` +> > Aquí estamos usando un solo corchete `["coat"]` reemplazando el número del índice con > > el nombre de la columna. Como el ejemplo 1, el objeto devuelto es un _list_. -> > -> > -> > ~~~ +> > ```{r, eval=TRUE, echo=TRUE} > > cats[1, 1] -> > ~~~ -> > {: .r} -> > -> > -> > -> > ~~~ -> > [1] calico -> > Levels: black calico tabby -> > ~~~ -> > {: .output} +> > ``` > > Este ejemplo usa un sólo corchete, pero esta vez proporcionamos coordenadas de fila y columna. > > El objeto devuelto es el valor en la fila 1, columna 1. El objeto es un _integer_ pero como > > es parte de un _vector_ de tipo _factor_, R muestra la etiqueta "calico" asociada con el valor entero. -> > -> > -> > ~~~ +> > ```{r, eval=TRUE, echo=TRUE} > > cats[, 1] -> > ~~~ -> > {: .r} -> > -> > -> > -> > ~~~ -> > [1] calico black tabby -> > Levels: black calico tabby -> > ~~~ -> > {: .output} +> > ``` > > Al igual que en el ejemplo anterior, utilizamos corchetes simples y proporcionamos > > las coordenadas de fila y columna. La coordenada de la fila no se especifica, > > R interpreta este valor faltante como todos los elementos en este _column_ _vector_. -> > -> > ~~~ +> > ```{r, eval=TRUE, echo=TRUE} > > cats[1, ] -> > ~~~ -> > {: .r} -> > -> > -> > -> > ~~~ -> > coat weight likes_string -> > 1 calico 2.1 TRUE -> > ~~~ -> > {: .output} +> > ``` > > De nuevo, utilizamos el corchete simple con las coordenadas de fila y columna. > > La coordenada de la columna no está especificada. El valor de retorno es una _list_ > > que contiene todos los valores en la primera fila. @@ -1327,106 +565,21 @@ str(cats[1,]) Por último, pero no menos importante están las matrices. Podemos declarar una matriz llena de ceros: -~~~ +```{r} matrix_example <- matrix(0, ncol=6, nrow=3) matrix_example -~~~ -{: .r} - - - -~~~ - [,1] [,2] [,3] [,4] [,5] [,6] -[1,] 0 0 0 0 0 0 -[2,] 0 0 0 0 0 0 -[3,] 0 0 0 0 0 0 -~~~ -{: .output} +``` Y de manera similar a otras estructuras de datos, podemos preguntar cosas sobre la matriz: - -~~~ +```{r} class(matrix_example) -~~~ -{: .r} - - - -~~~ -[1] "matrix" -~~~ -{: .output} - - - -~~~ typeof(matrix_example) -~~~ -{: .r} - - - -~~~ -[1] "double" -~~~ -{: .output} - - - -~~~ str(matrix_example) -~~~ -{: .r} - - - -~~~ - num [1:3, 1:6] 0 0 0 0 0 0 0 0 0 0 ... -~~~ -{: .output} - - - -~~~ dim(matrix_example) -~~~ -{: .r} - - - -~~~ -[1] 3 6 -~~~ -{: .output} - - - -~~~ nrow(matrix_example) -~~~ -{: .r} - - - -~~~ -[1] 3 -~~~ -{: .output} - - - -~~~ ncol(matrix_example) -~~~ -{: .r} - - - -~~~ -[1] 6 -~~~ -{: .output} +``` > ## Desafío 4 > @@ -1441,19 +594,10 @@ ncol(matrix_example) > > `length(matrix_example)`? > > > > -> > ~~~ +> > ```{r} > > matrix_example <- matrix(0, ncol=6, nrow=3) > > length(matrix_example) -> > ~~~ -> > {: .r} -> > -> > -> > -> > ~~~ -> > [1] 18 -> > ~~~ -> > {: .output} -> > +> > ``` > > Debido a que una matriz es un vector con atributos de dimensión añadidos, `length` > > proporciona la cantidad total de elementos en la matriz. > {: .solution} @@ -1476,12 +620,10 @@ ncol(matrix_example) > > Investiga como cambiar este comportamento. > > (Sugerencia: lee la documentación de la función **`matrix`**.) > > -> > -> > ~~~ +> > ```{r, eval=FALSE} > > x <- matrix(1:50, ncol=5, nrow=10) > > x <- matrix(1:50, ncol=5, nrow=10, byrow = TRUE) # to fill by row -> > ~~~ -> > {: .r} +> > ``` > {: .solution} {: .challenge} @@ -1496,12 +638,11 @@ ncol(matrix_example) > que hemos visto hasta ahora. > > > ## Solución al desafío 6 -> > -> > ~~~ +> > ```{r} > > dataTypes <- c('double', 'complex', 'integer', 'character', 'logical') > > dataStructures <- c('data.frame', 'vector', 'factor', 'list', 'matrix') > > answer <- list(dataTypes, dataStructures) -> > ~~~ +> > ``` > > {: .r} > > Nota: es útil hacer una lista en el pizarrón o en papel colgado en la pared listando > > todos los tipos y estructuras de datos y mantener la lista durante el resto del curso @@ -1514,14 +655,9 @@ ncol(matrix_example) > ## Desafío 7 > > Considera la salida de R para la siguiente matriz: -> -> ~~~ -> [,1] [,2] -> [1,] 4 1 -> [2,] 9 5 -> [3,] 10 7 -> ~~~ -> {: .output} +> ```{r, echo=FALSE} +> matrix(c(4, 1, 9, 5, 10, 7), ncol = 2, byrow = TRUE) +> ``` > ¿Cuál fué el comando correcto para escribir esta matriz? Examina > cada comando e intenta determinar el correcto antes de escribirlos. > Piensa en qué matrices producirán los otros comandos. @@ -1535,20 +671,15 @@ ncol(matrix_example) > > > > Considera la salida de R para la siguiente matriz: > > -> > ~~~ -> > [,1] [,2] -> > [1,] 4 1 -> > [2,] 9 5 -> > [3,] 10 7 -> > ~~~ -> > {: .output} +> > ```{r, echo=FALSE} +> > matrix(c(4, 1, 9, 5, 10, 7), ncol = 2, byrow = TRUE) +> > ``` > > ¿Cuál era el comando correcto para escribir esta matriz? Examina > > cada comando e intenta determinar el correcto antes de escribirlos. > > Piensa en qué matrices producirán los otros comandos. > > -> > ~~~ +> > ```{r, eval=FALSE} > > matrix(c(4, 1, 9, 5, 10, 7), ncol = 2, byrow = TRUE) -> > ~~~ -> > {: .r} +> > ``` > {: .solution} {: .challenge}