Taller 1. Primera parte. Fundamentos de Programación

Primer Punto.

1. Cree los siguientes vectores (todos los vectores deben tener 100 elementos):

a.)

a. Usando la función seq(), cree un vector que se llame id y contenga una lista de 100 números entre 10 y 80. Use la función que corresponda para confirmar que el vector tiene 100 elementos. No use el argumento by. En su lugar, revise cómo podría usar el argumento length.out.

id <- seq(10, 80, length.out = 100)
length(id)
## [1] 100

b.)

b. Un vector que se llame edad, generado de manera aleatoria que contenga números enteros entre 25 y 50 (Pista: Use la función sample()). Use la función que corresponda para verificar la clase o tipo de dato que es el vector edades. ¿Cuál es la clase o tipo de dato? Use la función que corresponda para mostrar los elementos de este vector que son mayores a 35.

edad <- sample(25:50, 100, replace = T)
typeof(edad)
## [1] "integer"
# Elementos mayores a 35

library(knitr)
kable(table(edad[edad > 35]), col.names = c("Edad", "Cantidad"))
Edad Cantidad
36 1
37 3
38 5
39 4
40 1
41 5
42 8
43 3
44 2
45 4
46 3
47 9
48 3
49 4
50 3

c.)

c. Observe que uno es un vector de números reales y el otro de números enteros. Si los dos usan sample(),¿por qué la diferencia?

Debido a que con la función sample() especificamos que nos arrojara 100 números del 25 al 50 y dicha función nos arroja una secuencia aleatoria de números enteros que se pueden repetir, mientas que con la función seq() solo le indicamos que hiciera una secuencia de números del 10 al 80 y que queríamos 100 números, dado que los números en este rango no son necesariamente enteros pueden tener decimales.

d.)

d. Un vector llamado nivel_desempeño que contenga, de manera aleatoria, las siguientes categorías: desempeño bajo, desempeño medio, desempeño alto y NA (Pista: Use la función sample()). Una vez haya creado este vector, conviértalo a un factor ordenado. NA no es una categoría de la variable, y por tanto no la debe incluir dentro de las categorías del factor.

categorias <- c("Desempeño bajo", "Desempeño medio", "Desempeño alto")
nivel_desempeño <- sample(c(categorias, NA), 100, replace = TRUE)
nivel_desempeño <- factor(nivel_desempeño, levels = categorias)
levels(nivel_desempeño)
## [1] "Desempeño bajo"  "Desempeño medio" "Desempeño alto"

e.)

e. Use la función que corresponda para determinar cuántas observaciones NO son valores faltantes en este vector.

sum(!is.na(nivel_desempeño))
## [1] 77

f.)

f. Usando el vector nivel_desempeño, cree un nuevo vector que se llame desempeño_completo y que solamente contenga los elementos del vector nivel_ desempeño que no sean valores faltantes.

desempeño_completo <- nivel_desempeño[!is.na(nivel_desempeño)]

g.)

g. Use la función que corresponda para saber el tamaño del vector del literal f.

length(desempeño_completo)
## [1] 77
Se comprueba que es el mismo número tanto en el punto e.) como en el g.)

h.)

h. Cree un data frame que se llame datos, en el que incluya los vectores id, edades, y nivel_desempeño.

datos <-  data.frame(round(id,1), edad, nivel_desempeño)
datos

i.)

i Use la función correspondiente para borrar todos los objetos que tiene actualmente en su espacio de trabajo.

rm(list = ls())

Segundo Punto.

2. Sea 1515 la semilla del generador de números aleatorios.

set.seed(1515)
# Sea:
x1 <- 1:10 + rnorm(n = 10, mean = 5, sd = 15)
# Sea:
x2 <- seq(22, 83, length.out = 10) + rnorm(n = 10, mean = 160, sd = 15)
# Sea:
x3 <- seq(73, 91, length.out = 10) + rnorm(n = 10, mean = 247, sd = 4)
# Sea:
y <- 2300 - 23.5 * x1 + 15 * x2 + 122 * x3
# Sea:
X1 <- round(t(x1), 2)
# Sea:
X2 <- round(t(x2), 2)
# Sea:
X3 <- round(t(x3), 2)
# Sea:
y <- round(t(y), 2)
  • Cree una matriz X de dimensión 10 × 3 y un vector y de dimensión 10 × 1

X <- matrix(data = c(X1, X2, X3), nrow = 10, ncol = 3)
X
##         [,1]   [,2]   [,3]
##  [1,]  -8.59 159.62 326.11
##  [2,]   7.29 194.99 316.00
##  [3,]  24.64 172.69 324.52
##  [4,] -11.47 222.51 320.37
##  [5,]  29.84 225.15 335.90
##  [6,]  -5.24 222.89 330.31
##  [7,]   6.13 198.83 342.94
##  [8,]  20.24 209.76 333.35
##  [9,]  18.51 231.34 336.81
## [10,]  16.10 246.26 343.73
y <- matrix(y, nrow = 10, ncol = 1)
y
##           [,1]
##  [1,] 44682.03
##  [2,] 43605.06
##  [3,] 43902.50
##  [4,] 44992.51
##  [5,] 45956.02
##  [6,] 46064.10
##  [7,] 46977.10
##  [8,] 45639.46
##  [9,] 46426.39
## [10,] 47550.91
  • Calcule \(\beta = (X^tX)^{-1}(X^ty)\)
beta <- round(solve((t(X) %*% X)) %*% (t(X) %*% y),2)
# Utilizo es solve() ya que ahí está pidiendo la inversa de la matriz, no que la eleve toda a la -1
beta
##        [,1]
## [1,] -25.07
## [2,]  14.34
## [3,] 129.41

Tercer Punto.

3. La criba de Eratóstenes, matemático griego, es un algoritmo que permite hallar todos los números primos menores que un número natural dado.

A continuación hay un pseudocódigo de una función que deben imitar completamente, ya que hay varias maneras de plantearlo. Deben ser obedientes al pseudocódigo.

La Data es la entrada a la función y Result es la salida (return) de la función.

Escriba el código de la función en R, ayudado de chatGPT. El resultado que entregue el código debe ser conforme al pseudocódigo y debe proporcionar un resultado correcto.

criba_eratostenes <-function(n){
   if (!is.numeric(n) || n < 1) {
    stop("La entrada no es un número natural mayor que 1")
   }
posibles<-seq(1, n, by=2)
  for(i in 2:round(sqrt(n))){
    if(posibles[i]!=0){
      for(j in seq(i + posibles[i], n/1, by=posibles[i])){
        posibles[j]<-0
      }
    }
  }
  return(posibles[posibles!=0])
}
as.vector(na.omit(criba_eratostenes(20)))
## [1]  1  3  5  7 11 13 17 19

En este punto ChatGPT no me arrojo un código que funcionara, sin embargo, fue de gran ayuda para poder estructurar el inicio de un código y que después por mi cuenta lo hiciera funcionar.

Cuarto Punto.

4. Cree una función usando la estructura de control if y else y un bucle for. Esta función debe tomar un vector que contiene nombres de unas carpetas. La función debe hacer lo siguiente: verificar si en el directorio de trabajo en que están trabajando existe cada una de las carpetas incluidas en el vector: Si la carpeta no existe debe crearla y debe mostrar el siguiente mensaje “La carpeta ________ fue creada con éxito”. Si la carpeta sí existe, la función debe mostrar un mensaje que diga “La carpeta ________ ya existe”. En el espacio en blanco debe presentar el nombre de la carpeta. Use las funciones dir.create() y dir.exist(). Pruebe el correcto funcionamiento de la función usando el siguiente vector: carpetas <- c(“Datos2”, “Escrito2”, “Resultados2”, “Imagenes2”, “Programas2”)

carpetas <- function(carpetas) {
  for (carpeta in carpetas) {
    if (!dir.exists(carpeta)) {
      dir.create(carpeta)
      cat("La carpeta", carpeta, "fue creada con éxito.\n")
    } else {
      cat("La carpeta", carpeta, "ya existe.\n")
    }
  }
}
carpetas(c("Datos2", "Escrito2", "Resultados2", "Imagenes2", "Programas2"))
## La carpeta Datos2 ya existe.
## La carpeta Escrito2 ya existe.
## La carpeta Resultados2 ya existe.
## La carpeta Imagenes2 ya existe.
## La carpeta Programas2 ya existe.

Quinto Punto

5. Escriba un bucle for para calcular la mediana de cada columna en la base de datos mtcars. Esta base se encuentra precargada en R. Pero en caso de estar ausente, cargue el paquete datasets. Para acceder a ella puede usar la función data(mtcars). La salida debe ser el nombre de la columna y su mediana correspondiente.

data(mtcars)
# Deseo crear primero una matriz vacía para después presentar los datos como una tabla.
num_columnas <- ncol(mtcars)
resultados <- matrix(NA, nrow = num_columnas, ncol = 2)
colnames(resultados) <- c("Columna", "Mediana")

for (i in 1:num_columnas) {
  resultados[i, ] <- c(names(mtcars[i]), round(median(mtcars[, i])))
}

library(knitr)
kable(resultados, align = "c")
Columna Mediana
mpg 19
cyl 6
disp 196
hp 123
drat 4
wt 3
qsec 18
vs 0
am 0
gear 4
carb 2

Sexto Punto.

6. Reemplace el código del bucle anterior usando:

a. Una función de la familia apply

resultados2 <- round(apply(mtcars, 2, median))

kable(data.frame(resultados2), col.names = "Mediana", align = "c")
Mediana
mpg 19
cyl 6
disp 196
hp 123
drat 4
wt 3
qsec 18
vs 0
am 0
gear 4
carb 2

b. La función map() del paquete purrr

# install.packages("purrr")
library(purrr)
resultados3 <- map(mtcars, median)

kable(data.frame(resultados3))
mpg cyl disp hp drat wt qsec vs am gear carb
19.2 6 196.3 123 3.695 3.325 17.71 0 0 4 2

Séptimo Punto.

7.Genere una función que imprima una de las tablas de la multiplicación: El usuario indica en el llamado a la función un número entero n (debe verificarse que es un número entero positivo), con el valor 10 por defecto y la función presenta en la consola la tabla de multiplicación para ese número. La tabla de multiplicación debe imprimirse en filas y columnas, de manera que la fila i y la columna j muestren el producto de i y j.

Por ejemplo, si el usuario ingresa el número 5, el programa debería imprimir:

# 1 2 3 4 5
# 2 4 6 8 10
# 3 6 9 12 15
# 4 8 12 16 20
# 5 10 15 20 25

Sugerencia: Puede utilizar un bucle for() para recorrer las filas de la tabla de multiplicación y otro bucle for() para recorrer las columnas de cada fila. Puede utilizar la función cat() para imprimir los números separados por espacios en la misma línea. Cuidar de cambiar de línea al final de cada fila.

# Se utilizó la misma estructura para reconocer si el número es positivo que en el punto 3.

multiplicacion <- function(n) {
   if (!is.numeric(n) || n < 0) {
    stop("Ingrese un número entero positivo.\n")
   }
  for (i in 1:n) {
    for (j in 1:n) {
      cat(i * j, " ")
    }
    cat("\n")
  }
}
multiplicacion(5)
## 1  2  3  4  5  
## 2  4  6  8  10  
## 3  6  9  12  15  
## 4  8  12  16  20  
## 5  10  15  20  25

Octavo Punto.

8. Explique línea a línea la siguiente función. Esto le implicará buscar la ayuda de los comandos que no conoce.

Numero_archivos <- function(ruta = path.expand('~')){
library(fs)
num_archivos <- list()
for (archivo in fs::dir_ls(ruta, type = "file")) {
extension <- path_ext(file.path(ruta, archivo))
if (length(extension) > 0) {
if (extension %in % names(num_archivos)) {
num_archivos[[extension]] <- num_archivos[[extension]] + 1
} else {
num_archivos[[extension]] <- 1
}
}
}
num_archivos <- data.frame("Cantidad" = unlist(num_archivos))
print(num_archivos)
}

Para la explicación debe usar el símbolo hashtag (#) en la línea previa a cada línea de instrucciones, como si estuviera comentando el código.

# Se define una función llamada Numero_archivos que toma una ruta de directorio como argumento.
Numero_archivos <- function(ruta = path.expand('~')){

# Carga el paquete fs que proporciona funciones para trabajar con el sistema de archivos.
library(fs)
  
# Crea una lista vacía llamada num_archivos para almacenar el recuento de archivos.
num_archivos <- list()
  
# Inicia un bucle for que itera a través de cada archivo en el directorio especificado.
for (archivo in fs::dir_ls(ruta, type = "file")) {
    
# Extrae la extensión del archivo actual y se la asigna en la variable extension.
extension <- path_ext(file.path(ruta, archivo))
    
# Verifica si la extensión es mayor que 0 (es decir, el archivo tiene una extensión).
if (length(extension) > 0) {
      
# Verifica si la extensión ya existe como un elemento en la lista num_archivos.
if (extension %in% names(num_archivos)) {
        
# Si la extensión ya existe, incrementa el contador para esa extensión en 1.
num_archivos[[extension]] <- num_archivos[[extension]] + 1
# Entonces.
} else {
        
# Si la extensión no existe en la lista num_archivos, agrega una nueva entrada con un valor inicial de 1.
num_archivos[[extension]] <- 1
}
}
}
  
# Convierte la lista num_archivos en un dataframe con una columna llamada "Cantidad" que contiene los recuentos de archivos por extensión.
num_archivos <- data.frame("Cantidad" = unlist(num_archivos))
  
# Imprime el dataframe que muestra la cantidad de archivos.
print(num_archivos)
}

Noveno Punto.

9. En algunos países de Europa del Este les enseñan a multiplicar de manera práctica mediante una alternativa a la que se enseña en Occidente:

Se toman los dos números a multiplicar y se escribe uno a la derecha del otro. Se calcula la mitad del de la izquierda, si es impar se desprenden del 0.5, y se escribe debajo del respectivo número. Se toma el de la derecha y se calcula el doble, y el resultado se escribe debajo del correspondiente número. Se realiza esta operación con el segundo par de números y así sucesivamente hasta que el de la izquierda sea uno.

A continuación proceda a tachar las líneas en que el número de la izquierda sea par. Sume la segunda columna de los que quedan. Ese es el resultado. Por ejemplo, sea la multiplicación de once por trece:

11 13

5 26

2 52 Línea a tachar

1 104

Total: 143

Escriba una función a la que le entran dos parámetros y realiza el cálculo de multiplicarlos mediante el procedimiento descrito.

multiplicacion_alternativa <- function(num1, num2) {
  resultado <- 0
  while (num1 > 0) {
    # Se comprueba si es par
    if (num1 %% 2 != 0) {
      resultado <- resultado + num2
    }
    # Izquierda.
    num1 <- (num1 %/% 2)
    # Derecha.
    num2 <- num2 * 2
  }
  return(resultado)
}

multiplicacion_alternativa(11, 13)
## [1] 143