-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path10-loop-for-if-else-multiples-elementos.Rmd
315 lines (198 loc) · 14.3 KB
/
10-loop-for-if-else-multiples-elementos.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# LOOP FOR E IF ELSE PARA MÁS DE UN ELEMENTO.
En este capítulo se se mostrará como usar el loop `for` que nos permitirá realizar múltiples procesos con una sencilla sintaxis. Asimismo, gracias al loop `for` podremos evaluar más de un elemento al usar las condicionales `if else`. Por último, veremos el uso de la función `ifelse()` que nos otorgará el mismo resultado que si usaramos el loop `for` con las condicionales `if else`.
## Loop for.
Gracias al loop `for` podremos realizar tareas similares automáticamente. El loop permite hacer el recorrido de todos los elementos de un vector con el fin de asignar a la operación procedente cada uno de los elementos del recorrido. La sintaxis del loop `for` es la siguiente:
`for (var in seq) {expression}`
Donde se le asigna un iterador (`var`), que puede ser cualquier letra o palabra, que hará el recorrido por el vector (`seq`) para asignar cada elemento de este en la `expresión`.
El iterador puede jugar el papel de objeto o de subobjeto, es decir, en el primer caso el iterador entra en la expresión como un objeto que será argumento de una función, en el segundo caso el iterador entra como un subobjeto de otro objeto y en conjunto servirán de argumento de una función.
### El iterador como objeto.
Veamos un ejemplo para que quede más claro. Vamos a imprimir el siguiente texto "Este es el número: ...", en los tres puntos asignaremos los números desde el 1 al 10.
```{r}
# Usando el loop for.
for (i in 1:10) {
print(paste0("Este es el número: ",i))
}
```
Primero, hemos asignado un iterador llamado `i` que hará el recorrido por todos los elementos del vector `1:10`, cada elemento lo usará en la ejecución de la expresión `print(paste0("Este es el número: ",i))`, es decir, el iterador `i` tomará cada uno de los elementos del vector `1:10` y los asignará en la expresión `print(paste0("Este es el número: ",i))`.
Gracias a esto hemos obtenido el resultado esperado en donde se ha impreso el texto "Este es el número: 1", "Este es el número: 2", y así sucesivamente hasta "Este es el número: 10".
Como se habrá podida dar cuenta una de las características principales del loop `for` en R es su sencilles para su uso. Se le invita a realizar la misma operación en otros softwares[^1] y verá la diferencia.
[^1]: Esta sencilles sólo puede ser semejante si usted usa el software python.
### El iterador como un subobjeto.
Ahora veamos un ejemplo en donde el vector por donde se hará el recorrido es una vector caracter.
```{r}
# Ejemplo usando un vector caracter.
x<-c("Azul","Rojo","Amarillo","Rosado","Marrón")
for (i in 1:length(x)) {
print(paste0("Este es el color: ",x[i]))
}
```
En esta ocasión hemos complicado un poco el uso, pero con el fin de que usted se de cuenta que el iterador también puede ser usado como un subobjeto, en este caso el iterador `i` es un subobjeto del objeto `x`.
Primero, se ha definido el vector `x` con los nombres: "Azul","Rojo","Amarillo","Rosado","Marrón". Posteriormente, en la sintaxis del loop `for` se ha asignado un iterador llamado `i` que hará el recorrido por el vector `1:length(x)`, es decir, desde el número 1 hasta el tamaño del vector `x` (desde 1 al 5). Cada uno de estos elementos se asignarán en la expresión `x[i]` (llamará a cada uno de los elementos del vector `x`, desde el primero al último, ya que se convertirá en `x[1]`, `x[2]`, `x[3]`, `x[4]` y `x[5]`).
Lo principal de este ejemplo, es darse cuenta de la importancia que juega el iterador que ya no solo juega el papel de objeto, como en el primer ejemplo, sino como subobjeto de otro objeto.
Quizá le parezca un poco complicado al inicio, pero como se comentó al inicio este loop puede ser escrito de una manera más sencilla, a continuación, se muestra la sintaxis.
```{r}
# El ejemplo 2 con una sintaxis más sencilla.
for (i in x) {
print(paste0("Este es el color: ", i))
}
```
En este caso se puede observar que el iterador juega el papel de objeto. ¿Cómo así? El iterador `i` recorrerá el vector `x`, es decir, todos los elementos de `x` ("Azul","Rojo","Amarillo","Rosado","Marrón") y los asignará en la expresión `print(paste0("Este es el color: ", i))`.
Usted se puede estar preguntando ¿Cuál es el fin de colocar al iterador como subobjeto si la sintaxis es más sencilla considerando al iterador como objeto? En el ejemplo que hemos visto y por su sencilles es más fácil usar al iterador como objeto, pero cuando avancemos más y deseemos hacer loops más complicados en donde haya más de un iterador o dentro de funciones, tendremos que usar al iterador como subobjeto. Así que por el momento es preciso aprender las dos formas.
Avancemos un poco más y realicemos un ejemplo un poquillo más complicado.
Vamos a realizar un loop en el cual se guardan los resultados en un vector externo.
```{r}
# Guardando los resultados en un vector externo.
x<-c()
for (t in 1:5) {
y<-t^2
x<-c(x,y)
}
```
Primero hemos creado un vector vacio `x` donde guardaremos los resultados del loop, posteriormente en el loop `for` se asigna el iterador `t` que hará el recorrido por el vector `1:5`, asignando cada elemento en la expresión `y<-t^2; x<-c(x,y)`. Lo que hará será elevar los elementos del vector `1:5` al cuadrado y guardarlo en el objeto `y`. En la expresión `x<-c(x,y)` le decimos al software que guarde en el objeto `x` el vector que se genera al juntar el objeto `x` con el objeto `y`. Como el valor de `y` cambiará con cada elemento ya que el iterador tomará uno por uno los elementos del vector `1:5`, entonces, es preciso guardar cada resultado.
Para observar que se ha guardado en el objeto `x` corramos este vector.
```{r}
x
```
Como se puede dar cuenta el vector `x` tiene los elementos `r x` que resultan al elevar cada elementos del vector `1:5` al cuadrado.
Usted puede ser perpicaz y al haber leído todos los capítulos de este libro, usted puede decir que el resultado anterior saldría solo con ejecutar `(1:5)^2`. En efecto, sí, el resultado es el mismo, pero repito, por el momento estamos haciendo ejemplos muy sencillos para que se tenga una total comprensión de los usos del loop `for`.
## El loop for con las condicionales if else.
Usted recuerda del capítulo anterior la unicidad de las condicionales `if else`, el cual implicaba que solo se evaluara el primer elemento de un vector. Ahora gracias al loop `for` podremos evaluar todos los elementos del vector.
Veamos un ejemplo en donde se da a conocer el problema y cómo podríamos solucionar esto usando el loop `for`.
El ejemplo es el siguiente, queremos saber que elementos del vector `p` son menores a 30, y si es así que imprima los elementos. Es obvio que tenemos que usar la condicional `if`.
```{r}
# Creando el vector p.
set.seed(3000)
p<-sample(20:50, 20, T)
# El vector p tiene los elementos.
p
```
```{r, eval=FALSE}
# Realizando la condicional if.
if(p<30){
print(p)
}
# Error in if (p < 30) { : the condition has length > 1
```
¿Cómo es posible que no haya impreso ningún elemento? Como se mencionó, la condicional `if` sólo evaluó el primer elemento del vector `p` y este al no ser `r p[1]` menor que 30, nos resulta que la prueba lógica `p<30` es `FALSE` por lo cual no ejecuta el proceso `print(p)`.
Entonces, estamos atados de manos, pero usted puede observar una posible solución usando la siguiente sintaxis:
```{r}
if(p[1]<30){
print(p)
}
if(p[2]<30){
print(p)
}
if(p[3]<30){
print(p)
}
# Así sucesivamente hasta
if(p[20]<30){
print(p)
}
```
Pero esto no es para nade eficiente, y sería un demente si pierde su tiempo escribiendo esa sintaxis.
Entonces, nuestra salvación es el loop `for`. A continuación se muestra la sintaxis usando al iterador como un objeto.
```{r}
# Resolviendo el problema usando el loop for.
for (i in p) {
if(i<30){
print(i)
}
}
```
Y a continuación la solución usando al iterador como un subobjeto.
```{r}
# Resolviendo el problema usando el loop for.
for (i in 1:length(p)) {
if(p[i]<30){
print(p[i])
}
}
```
Con estas soluciones se puede observar el tiempo que nos hemos ahorrado si sabemos usar correctamente el loop `for`.
Ahora veamos otro ejemplo en donde tenemos el vector sexo que tiene 30 elementos que pueden ser 0 y 1. Asimismo, nos indican que 0 indica que el sexo es femenino y que 1 indica que el sexo es masculino. Entonces, nos piden que cambiemos los 0 y 1 por los nombres femenino y masculino.
Con los conocimientos que tenemos podemos aplicar el loop for de la siguiente manera.
```{r}
# creando el vector sexo.
set.seed(2021)
sexo<-sample(0:1, 30, T)
# Los elementos del vector sexo.
sexo
# Aplicando el loop for.
for (i in 1:length(sexo)) {
if(sexo[i]==0){
sexo[i]<-"Femenino"
} else if (sexo[i]==1){
sexo[i]<-"Masculino"
}
}
```
Estamos usando el método donde se considera al iterador como subobjeto ¿Le invitamos a realizar el mismo ejericio pero usando el iterador como objeto? ¿Con qué método le resultó más fácil?
Viendo como quedó el vector `sexo` luego de aplicar el loop `for`.
```{r}
sexo
```
En efecto, todos los elementos que eran 0 se han cambiado por "Femenino" y todos los que era 1 se han cambiado por "Masculino".
Estoy seguro que usted se está preguntando ¿Todo eso para cambiar los 0 por "Femenino" y los 1 por "Masculino"? En realidad sí. ¿Pero si con otros softwares se obtiene el mismo resultado muchó más fácil? En realidad sí. Pero repito, aquí estamos viendo las formas de usar el loop `for` con la condicional `if else`. Esto que parece innecesario, a la hora de aplicarlo a matrices, listas o dataframe será tan útil y verá la facilidad con lo que resuelve futuras cuestiones. Veremos estas aplicaciones más útiles cuando completemos el tema de data frame, por el momento, será suficiente con conocer como se aplica el loop con sus dos variantes. Pero sí ha quedado insatisfecho, a continuación, se muestra como resolver este tipo de cuestiones usando la función `ifelse()`.
## Función ifelse().
Una forma de realizar el proceso anterior sin la necesidad de usar el loop `for` explícitamente y sin tanto código, es usar la función `ifelse()`, el cuál realiza el loop `for` implícitamente y resulta muchísimo más sencillo de usar. Pero como todo proceso que genere simplicidad, solo servirá para un número pequeño de aplicaciones, por lo cual, no englobará en al loop `for`.
Vamos a realizar el mismo ejercicio que el anterior.
```{r}
# creando el vector sexo.
set.seed(2021)
sexo<-sample(0:1, 30, T)
# Los elementos del vector sexo.
sexo
# Resolviendo con la función ifelse.
ifelse(sexo==0,"Femenino","Masculino")
```
Y en efecto, hemos obtenido el mismo resultado.
¿Cómo se hizo?
La función `ifelse()` tiene la siguiente sintaxis.
`ifelse(test, yes, no)`
En donde el primero argumento `test` es una prueba lógica que puede ser TRUE o FALSE; el segundo argumento `yes` es el valor que retornará la función si el `test` resulta TRUE; por último, el argumento `no` es el valor que retornará la función si el `test` resulta FALSE.
En ese sentido, la prueba lógica o `test` en nuestro ejemplo fue `sexo==0`, en `yes` hemos asignado el valor de "Femenino" y en `no` el valor de "Masculino", lo que implica que si la variable `sexo==0` es TRUE, entonces asignará "Femenino", pero si es FALSE asignará "Masculino".
El uso de esta función es muy sencilla y puede anidarla. Para observar un pequeño ejemplo supongamos que tenemos el vector civil, el cual tiene elementos entre 0, 1 y 2. Y nos indican que 0 es soltero, 1 casado y 2 viudo.
```{r}
# Creando el vector civil.
set.seed(2021)
civil<-sample(0:2, 20, T)
# Viendo los elementos del vector civil.
civil
# Resolviendo el problema usando la función ifelse.
ifelse(civil==0, "Soltero",
ifelse(civil==1, "Casado", "viudo"))
```
En efecto, hemos obtenido el resultado esperado. Cuando se vea los capítulos del paquete `dplyr` se mostrará el uso de la función `case_when()` que realiza el mismo procedimiento que la función `ifelse()`, pero con una menor sintaxis y con código más limpio y entendible.
## Declaración Break y Next.
En R se tiene las declaraciones `break` y `next`. La declaración `break` nos permite detener el loop `for` o el ciclo `while`[^2], mientras que la declaración `next` nos permite saltar una deteminada iteración en el loop `for`. Veamos a continuación la aplicación de cada uno.
[^2]: El ciclo while se desarrollará en el siguiente capítulo.
Como se mencionó la declaración `break` detiene el loop `for` siempre y cuando una determinada condición lógica sea `TRUE`. Por ejemplo, vamos a imprimir las letras del abecedario hasta la letra H. Una vez que se ha impreso la letra H que se detenga el loop `for`.
Para esto vamos a usar la función `LETTERS` que nos arroja las letras del abecedario en mayúscula.
```{r}
# Las letras del abecedario en mayúscula.
LETTERS
# Construyendo el loop for.
for (i in LETTERS) {
if(i=="H"){
print(i)
break
} else {
print(i)
}
}
```
En efecto, solo se ha impreso hasta la letra "H". Pero ¿cómo sucedió? Primero, si nosotros no consideramos a la declaración `break` el loop `for` hubiese impreso todas las letras del abecedario. Entonces, al incluir el `break` le decimos al software que cuando el iterador sea igual a "H" entonces imprima la letra de la iteración y que detenga el loop. Ahora, si no se cumple la condión, entonces que imprima la letra de la iteración. Es así que cuando el iterador vale "H" se cumple la condición entonces imprime "H" y detiene el loop.
Por otro lado, la declaración `next` nos permite saltar la iteración siempre y cuando la condición lógica sea `TRUE`. Veamos un ejemplo para ver su aplicación.
Por ejemplo, vamos a ser el mismo loop que en el ejemplo anterior, pero ahora vamos a saltar la iteración, siempre y cuando la iteracción sea igual a la letra "H". Es decir, si la iteración es igual a "H" entonces no será impreso.
```{r}
for (i in LETTERS) {
if(i=="H"){
next
} else {
print(i)
}
}
```
Y en efecto, no se ha impreso la letra "H" y esto sucede porque en la sintaxis indicamos que si el iterador es igual a "H" entonces ejecute `next`, es decir, no imprima a la letra "H".
En el siguiente capítulo veremos el tema del ciclo `while()` que es complementario al ciclo `for()`. Este ciclo, también usa las declaraciones `next` y `break`, incluso, su aplicación es más útil que en el loop `for()`.