Apéndice 2: Soluciones a ejercicios seleccionados

Hay muchas maneras de resolve los problemas propuestos a lo largo del libro. Las que se muestran en este apéndice no son las mejores en general; pero las respuestas propuestas para los problemas del capítulo 3, por ejemplo, están entre las mejores que cabe esperar de quien solo conozca el contenido de los capítulos 1, 2 y 3.

De hecho, muchos de los problemas están planteados directamente como meros ejercicios prácticos y aplicación casi inmediata del contenido que los circunda.

Solución al Ejercicio 1.1

Al hacer

plot(iris)

se ven claramente patrones como los siguientes:

  • Existen tres especies distintas.
  • Existe una relación más o menos lineal entre la longitud y la anchura de los pétalos.
  • Una de las especies tiene características muy distintas del resto, mientras que las otras dos son más parecidas entre sí.

Solución al Ejercicio 1.2

Entre otras cosas, tienen que quedar claras las dimensiones de la tabla y las características (numéricas, alfanuméricas, etc.) de las columnas. Para las columnas numéricas se obtiene una indicación del tamaño (o la distribución) de los valores.

Solución al Ejercicio 1.3

head(iris, 10)

Solución al Ejercicio 1.4

Las llamadas

summary(airquality)
dim(airquality)
colnames(airquality)

proporcionan la información requerida y

head(airquality, 13)

las 13 primeras filas.

Solución al Ejercicio 1.5

summary(attenu)

deja claro que la columna station tiene 16 valores nulos.

Solución al Ejercicio 1.7

iris[iris$Petal.Length > 4,]

Solución al Ejercicio 1.8

mtcars[mtcars$cyl < 6 & mtcars$gear == 4,]

Solución al Ejercicio 1.9

mi_copia <- airquality
ls()
mi_copia$temperatura <- mi_copia$temperatura
head(mi_copia)    # por ejemplo
mi_copia$temperatura <- NULL
rm(mi_copia)

Solución al Ejercicio 1.10

tmp <- CO2[(CO2$Treatment == "chilled") & (CO2$uptake > 15),]
head(tmp, 10)

También se puede resolver en una sola línea. A veces hay que equilibrar concisión y legibilidad y eso depende frecuentemente del estilo y personalidad de cada cual.

Los paréntesis no son estrictamente necesarios —compruébalo—, pero no está de más añadirlos, por claridad.

Solución al Ejercicio 1.12

res <- iris[order(iris$Species, iris$Petal.Length),]

Solución al Ejercicio 1.13

Fue el 5 de mayo (ordena la tabla y examina el resultado).

Solución al Ejercicio 1.14

El día 11 (ordena la tabla después de filtrar y quedarte solo con el mes de junio).

Solución al Ejercicio 1.15

paro <- read.table("paro.csv", header = TRUE, sep = "\t")

Presta atención a cómo se indica que el separador es un tabulador. Por supuesto, dependiendo de cuál sea tu directorio de trabajo, tendrás que modificar o no la ruta a paro.csv.

Solución al Ejercicio 1.16

El indicion más claro de que has indicado mal el separador del fichero es que la tabla resultante tiene una única columna en la que aparecen todos los datos apelotonados.

Solución al Ejercicio 1.18

datos <- read.table("https://datanalytics.com/uploads/datos_treemap.txt",
                    header = TRUE, sep = "\t")

Solución al Ejercicio 1.19

tmp_file <- tempfile()
download.file("https://datanalytics.com/uploads/datos_treemap.txt", tmp_file)
datos <- read.table(tmp_file, header = TRUE, sep = "\t")

En el código anterior, hemos usado tempfile (consulta tempfile) para crear un fichero en un directorio temporal en el que luego hemos descargado el fichero de internet. Finalmente, se ha leído como cualquier otro fichero.

El fichero permanecerá en el directorio temporal hasta ser borrado explícitamente o hasta que se cierre la sesión de R.

Solución al Ejercicio 1.24

Si tienes problemas con este ejercicio, consulta los ejemplos que aparecen en ?png.

Solución al Ejercicio 1.27

plot(iris$Petal.Length, iris$Petal.Width)

El gráfico sugiere, al menos, dos cosas: una relación lineal entre las variables y la existencia de dos grupos diferenciados. ¿Crees que puedes diferenciarlos?

Solución al Ejercicio 1.31

La inspección del gráfico sugiere que, para identificar el outlier, se puede hacer:

iris[iris$Species == 'setosa' & iris$Sepal.Width < 2.5,]

Solución al Ejercicio 1.32

boxplot(airquality$Temp ~ airquality$Month)

Solución al Ejercicio 1.34

mean(airquality$Temp)
mean(airquality$Temp[airquality$Month == 5])
tail(airquality[order(airquality$Wind),], 1)
# o bien
airquality[which.max(airquality$Wind),]

Solución al Ejercicio 1.37

hist(airquality$Temp)
abline(v = mean(airquality$Temp), col = "red")

Solución al Ejercicio 1.38

pisa <- read.csv("pisasci2006.csv")
which(pisa$Country == "Spain")
pisa[pisa$Country == "Spain",]

plot(pisa$Income, pisa$Overall)

pisa[pisa$Income > .9 & pisa$Overall < 400,]

hist(pisa$Overall)
abline(v = pisa$Overall[pisa$Country == "Spain"], col = "red")

Solución al Ejercicio 2.1

1:nrow(iris)

Solución al Ejercicio 2.2

seq(1, 2, by = .1)

# o bien,

1 + 0:10 / 10

Solución al Ejercicio 2.3

iris[, c(1, 3, 5)]

Solución al Ejercicio 2.4

iris[c(1:4, 100:104),]

Solución al Ejercicio 2.5

airquality[, c("Wind", "Temp")]

Solución al Ejercicio 2.6

iris[rep(1, 100),]

Solución al Ejercicio 2.7

table(CO2$Type)

Solución al Ejercicio 2.9

x <- 1:10
x[1:(length(x) - 2)]

Solución al Ejercicio 2.10

x <- 1:10
x[-1] - x[-length(x)]

diff(x)

Solución al Ejercicio 2.11

mi_iris <- iris
colnames(mi_iris)[1:2] <- c("Longitud.Sepalo", "Anchura.Sepalo")

Solución al Ejercicio 2.12

iris[sample(1:nrow(iris), 30),]

Solución al Ejercicio 2.13

Hay varias maneras de resolver este problema. Por ejemplo,

indices <- sample(1:nrow(iris), 75)
parte_01 <- iris[indices,]
parte_02 <- iris[-indices,]

Alternativamente,

tmp <- iris[sample(nrow(iris)),]
parte_01 <- head(iris, 75)
parte_02 <- tail(iris, 75)

¿Se te ocurre alguna más?

Solución al Ejercicio 2.18

Muestra los casos más frecuentes (y sus respectivas frecuencias).

Solución al Ejercicio 2.22

x <- 0:1e6
x <- (-1)^x / (2*x + 1)
sum(x)

Solución al Ejercicio 2.24

mi_prod <- function(x) exp(sum(log(x)))

Solución al Ejercicio 2.26

tapply(airquality$Temp, airquality$Month, mean)

Solución al Ejercicio 2.27

tapply(airquality$Ozone, airquality$Month, mean, na.rm = T)

Solución al Ejercicio 2.28

tapply(mtcars$hp, mtcars$cyl, median)

Solución al Ejercicio 2.30

rep(letters, times = 26:1)

Solución al Ejercicio 2.31

reps <- rep(letters, times = 26:1)
frecuentes <- names(tail(sort(table(reps)), 5))
reps[!reps %in% frecuentes] <- "otros"

Solución al Ejercicio 2.32

pop <- rep(0, 1e6)
pop[1:1e5] <- 1
encuesta <- sample(pop, 1000)
100 * mean(encuesta)

Solución al Ejercicio 2.34

pop <- rep(0, 1e6)
pop[1:1e5] <- 1
encuestas <- replicate(500, 100 * mean(sample(pop, 1000)))
hist(encuestas)

Solución al Ejercicio 3.1

wilcox.test(sleep$extra ~ sleep$group)

Solución al Ejercicio 3.3

modelo <- lm(Ozone ~ Temp, data = airquality)
plot(airquality$Temp, airquality$Ozone)
abline(modelo, col = "red")

Solución al Ejercicio 3.4

Para aplicar el test de proporciones se puede hacer lo siguiente:

datos <- as.data.frame(UCBAdmissions)
datos$Admit <- datos$Admit == "Admitted"
h <- datos[datos$Gender == "Male",]
m <- datos[datos$Gender != "Male",]

h_a <- sum(h$Freq[h$Admit])
m_a <- sum(m$Freq[m$Admit])

prop.test(c(h_a, m_a),
          c(sum(h$Freq), sum(m$Freq)))

Los p-valores son idénticos, pero es engañoso: en ambos casos están en el límite inferior de lo que muestra R. Si el p-valor fuese mayor, se vería que —particularmente, si no se aplica la llamada _corrección de Yates— coinciden. Para más información, véase esto.

Solución al Ejercicio 4.3

La misma función que para vectores: c.

Solución al Ejercicio 4.4

a <- list(a1 = 2, a2 = 7)
a$a1 <- NULL

Solución al Ejercicio 4.6

Una obtiene el elemento en cuestión. La otra, una lista que contiene a dicho elemento. Es la misma diferencia que hay entre un vaso con agua y el agua que contiene el vaso.

Solución al Ejercicio 4.7

a <- list()

Solución al Ejercicio 4.9

Es una lista con tres componentes, cada uno de los cuales es una tabla con cincuenta filas.

Solución al Ejercicio 4.10

sapply(tmp, dim)
lapply(tmp, dim)

Solución al Ejercicio 4.12

tmp <- rep(letters[1:5], each = 30)
tmp <- sample(tmp)
res <- split(iris, tmp)

Solución al Ejercicio 4.14

Porque cada elemento de la entrada puede partirse en un número desigual de bloques.

Solución al Ejercicio 4.15

mi_lista <- list(a = 1:3, b = c("hola", "adiós"))

sum(mi_lista$a)
mi_lista$b <- c(mi_lista$b, "hasta luego")
sapply(mi_lista, length)
mi_lista$iris <- iris
mi_lista$a <- NULL

Solución al Ejercicio 6.4

grep("[0-9]", colors(), value = TRUE)
grep("^yellow", colors(), value = TRUE)
grep("blue", colors(), value = TRUE)
gsub("[0-9]", "x", colors())
gsub("[0-9]+", "x", colors())

Solución al Ejercicio 6.5

paises_por_pib$usd <- as.numeric(
    gsub(" ", "",
    paises_por_pib[["Dólaresinter-nacionales"]]))

Solución al Ejercicio 6.6

dat <- data.frame(
    a = 1:3,
    b = c("20,34", "1.345,42", "1.234.5678,90"))

dat$b <- gsub("\\.", "", dat$b)
dat$b <- gsub(",", ".", dat$b)
dat$b <- as.numeric(dat$b)

Solución al Ejercicio 6.7

ficheros <- c("ventas_20220522_zaragoza.csv",
               "pedidos-firmes_20220422_soria.csv")

ficheros <- gsub(".csv", "", ficheros)
ficheros <- strsplit(ficheros, "_")
ficheros <- as.data.frame(do.call(rbind, ficheros))
colnames(ficheros) <- c("nombre", "fecha", "provincia")
ficheros$fecha <- as.Date(ficheros$fecha, "%Y%m%d")

Solución al Ejercicio 6.8

coords <- c("41°39'00''N","0°53'00''O")

grados <- as.numeric(gsub("°.*", "", coords))
minutos <- as.numeric(gsub(".*°([0-9]*)'.*", "\\1", coords))
segundos <- as.numeric(gsub(".*'([0-9]*)''.*", "\\1", coords))

coords_dec <- grados + minutos / 60 + segundos / 3600

Solución al Ejercicio 7.1

wilcox.test(sleep$extra ~ sleep$group)

Solución al Ejercicio 7.1

wilcox.test(sleep$extra ~ sleep$group)

Solución al Ejercicio 7.1

wilcox.test(sleep$extra ~ sleep$group)

Solución al Ejercicio 7.1

wilcox.test(sleep$extra ~ sleep$group)

Solución al Ejercicio 7.1

wilcox.test(sleep$extra ~ sleep$group)

Solución al Ejercicio 7.1

wilcox.test(sleep$extra ~ sleep$group)

Solución al Ejercicio 7.1

wilcox.test(sleep$extra ~ sleep$group)

Solución al Ejercicio 7.1

wilcox.test(sleep$extra ~ sleep$group)

Solución al Ejercicio 7.1

wilcox.test(sleep$extra ~ sleep$group)

Solución al Ejercicio 7.1

wilcox.test(sleep$extra ~ sleep$group)

Solución al Ejercicio 7.1

wilcox.test(sleep$extra ~ sleep$group)

Solución al Ejercicio 7.1

wilcox.test(sleep$extra ~ sleep$group)

Solución al Ejercicio 7.1

wilcox.test(sleep$extra ~ sleep$group)