Operadores - R para principiantes

Operadores – R para principiantes

Me encuentro trabajando en una segunda edición del libro R para principiantes. El siguiente artículo corresponde al capítulo 6 de esta edición.

Los operadores, como su nombre los indica, son símbolos usados por R para realizar diferentes tipos de operaciones. En todos los lenguajes de programación, los operadores son sumamente importantes, al combinarlos con los datos y sus estructuras es como logramos hacer la mayor parte de nuestro trabajo.

Los tipos de operadores principales en R son los siguientes:

  • Aritméticos
  • Relacionales
  • Lógicos
  • De asignación

Revisemos sus características.

6.1 Operadores aritméticos

Este tipo de operador es usado para operaciones aritméticas. En R tenemos disponibles los siguientes operadores, que corresponden a las operaciones aritméticas básicas.

OperadorOperaciónEjemploResultado
+Suma5 + 38
-Resta5 - 32
*Multiplicación5 * 318
/División5 /31.666667
^Potencia5 ^ 3125
%%División entera5 %% 32

Podemos realizar operaciones aritméticas con datos de tipo entero y numérico.

Si escribimos una operación aritmética en la consola de R y damos Enter, la operación se realiza y nos es devuelto su resultado.

15 * 3
[1] 45

Cuando intentamos realizar una operación aritmética con un tipo de dato que no sea entero o numérico, R primero intentará coercionar ese dato a uno de tipo numérico. Si la coerción es exitosa, se realizará la operación normalmente, y si falla nos devolverá un error.

Por ejemplo, 4 + TRUE se realizará normalmente, coercionando TRUE a 1.

4 + TRUE
[1] 5

En contraste, si intentamos la operación 4 + "1" se nos devuelve un error.

4 + "1"
Error in 4 + "1": non-numeric argument to binary operator

El mensaje “non-numeric argument for binary operator” aparecerá siempre que intentemos realizar una operación aritmética con un argumento no numérico y que no puede coercionarse a tipo numérico. Si nos encontramos con este error, esto nos da una pista para encontrar la raíz del problema.

Cualquier operación aritmética que intentemos con un dato NA siempre nos devolverá NA como resultado a menos que ocurra un error o un dato sea NULL.

NA - 66
[1] NA
21 * NA
[1] NA
NA ^ 13
[1] NA
"64.3" + NA
Error in "64.3" + NA: non-numeric argument to binary operator

¿Qué pasa si hacemos una operación con un dato NULL? Siempre nos devolverá un vector numérico vacío, incluso si uno de los datos es NA, a menos que ocurra un error.

NULL - 66
numeric(0)
21 * NULL
numeric(0)
NULL ^ 13
numeric(0)
NULL + NA
integer(0)
"64.3" + NULL
Error in "64.3" + NULL: non-numeric argument to binary operator

6.1.1 La división entera

La división entera o módulo es un caso particular de la división, que en lugar de devolver el cociente de la operación, nos devuelve el residuo.

Por ejemplo, si hacemos la división 4 / 2 obtenemos su cociente, 2.

4 / 2
[1] 2

Si hacemos una división entera de 4 entre 2, el resultado será 0, por ser una división exacta que no tiene residuo.

4 %% 2
[1] 0

En cambio, si hacemos una división 5 / 2, su resultado es 2.5. Obtenemos una parte decimal en el resultados porque no podemos hacer una división exacta entre estos dos números.

5 / 2
[1] 2.5

Por lo tanto, al hacer la división entera de 5 entre 2, el resultado será 1, el residuo de la división.

5 %% 2
[1] 1

6.2 Operadores relacionales

Los operadores lógicos son usados para hacer comparaciones y siempre devuelven como resultado los valores lógicos TRUE o FALSE (verdadero o falso, respectivamente).

OperadorComparaciónEjemploResultado
<Menor que5 < 3FALSE
>Mayor que5 > 3TRUE
<=Menor o igual que5 <= 3FALSE
>=Mayor o igual que5 >= 3TRUE
==Exactamente igual que5 == 3FALSE
!=No es igual que5 != 3TRUE

6.2.1 Comparación de datos enteros o numéricos

Al comparar datos enteros o numéricos ocurre una comparación de magnitudes.

16 > 8.5
[1] TRUE
16 < 8.5
[1] FALSE
-16 > -8.5
[1] FALSE
-16 < -8.5
[1] TRUE
8.5 >= 8.5
[1] TRUE
8.5 <= 8.5
[1] TRUE
8.5 == 8.5
[1] TRUE
16 == 8.5
[1] FALSE
8.5 != 8.5
[1] FALSE
16 != 8.5
[1] TRUE

6.2.2 Comparación de cadenas de texto

Cuando usamos los operadores >>=< y <= con cadenas de texto, se hace una comparación por orden alfabético.

Por ejemplo, probemos si "casa" es mayor que "barco".

"casa" > "barco"
[1] TRUE

En este caso, es verdadero que la palabra “casa” tiene orden alfabético mayor a “barco”, pues empieza con “c” y esta letra tiene una posición posterior a la “b” en el alfabeto.

Entonces, si comparamos "barco" < "casa" no es devuelto FALSE.

"barco" < "casa"
[1] TRUE

La comparación es hecha letra por letra, de modo que "casa" tiene un orden alfabético mayor que "cama" y menor que "cava".

"casa" > "cama"
[1] TRUE
"casa" > "cava"
[1] FALSE

Al comparar dos cadenas con == ambas deben ser exactamente iguales para que nos sea devuelto TRUE, si son parcialmente iguales obtenemos FALSE.

"casa" == "casa"
[1] TRUE
"casa" == "casar"
[1] FALSE

Las comparaciones son sensibles a las letras mayúsculas y minúsculas. Las letras mayúsculas tienen un orden mayor que las minúsculas.

"C" > "c"
[1] TRUE
"Barco" > "barco"
[1] TRUE
"barco" > "barCo"
[1] FALSE

6.2.3 Comparación de factores

Si intentamos comparar dos factores se nos devuelve un valor NA y una advertencia de que la operación de relación no tiene significado para factores.

factor("1") > factor("2")
Warning in Ops.factor(factor("1"), factor("2")): '>' not meaningful for factors
[1] NA

Esto ocurre incluso cuando comparamos factores que forman parte del mismo vector.

vector_factores <- factor(c("1", "2"))

vector_factores
[1] 1 2
Levels: 1 

vector_factores[1] > vector_factores[2]
Warning in Ops.factor(vector_factores[1], vector_factores[2]): '>' not meaningful for factors
[1] NA

6.2.4 Comparación con datos lógicos

Al comparar valores lógicos, TRUE siempre es mayor que FALSE.

TRUE < FALSE
[1] FALSE
TRUE > FALSE
[1] TRUE

Naturalmente, TRUE y FALSE son iguales a sí mismos y diferentes entre sí.

TRUE == TRUE
[1] TRUE
FALSE == FALSE
[1] TRUE
TRUE == FALSE
[1] FALSE
TRUE != FALSE
[1] TRUE

6.2.5 Comparación con NA y NULL

Cualquier comparación con un dato NA nos devuelve NA, excepto al comparar con NULL.

NA > 32
[1] NA
NA > "32"
[1] NA
NA > TRUE
[1] NA

Por su parte, cualquier comparación un dato NULL obtenemos un vector lógico vacío, incluso al comparar con un dato NA.

NULL < 32
logical(0)
NULL < "32"
logical(0)
NULL < TRUE
logical(0)
NULL < NA
logical(0)

6.2.6 Comparación con datos de diferentes tipos

Si comparamos un dato numérico con una cadena de texto, el dato entero o numérico es coercionado a una cadena de texto y se seguirán las reglas de comparación para cadenas.

"1" == 1
[1] TRUE
"a" > 123000.75
[1] TRUE
"33" > 40
[1] FALSE
"33" > 22.1
[1] TRUE

Como las números en una cadena de texto tienen un orden alfabético menor que las letras, generalmente una palabra será mayor que un dato entero o numérico

"Alba" > 137018.75
[1] TRUE
"zócalo" > 137018.75
[1] TRUE

Si comparamos un dato númerico con uno lógico, TRUE es coercionado a 1 y FALSE a 0.

TRUE == 1
[1] TRUE
FALSE == 0
[1] TRUE
TRUE > 24
[1] FALSE
FALSE > 24
[1] FALSE
TRUE > -24
[1] TRUE
FALSE > -24
[1] TRUE

Si comparamos un valor lógico con una cadena de texto, este será coercionado a una cadena de texto, así que se compararán "TRUE" y "FALSE", con las reglas de comparación para cadenas de texto.

TRUE == "TRUE"
[1] TRUE
FALSE == "FALSE"
[1] TRUE
TRUE > "SOGA"
[1] TRUE
TRUE > "UMBRAL"
[1] FALSE
FALSE > "ETAPA"
[1] TRUE
FALSE > "HIGO"
[1] FALSE

6.3 Operadores lógicos

Los operadores lógicos son usados para operaciones de álgebra Booleana, es decir, para describir relaciones lógicas, evaluándolas como verdaderas (TRUE) o falsas (FALSE).

OperadorNombreOperaciónEjemploResultado
a | bO (OR)o b es verdaderoTRUE | FALSETRUE
a & bY (AND)y b son verdaderosTRUE & FALSEFALSE
!aNO (NOT)no es verdadero!TRUEFALSE

Estos operadores siempre devuelven TRUE o FALSE, sin importar el tipo de datos con los que se opere.

Los operadores | y & siguen estas reglas:

  • | devuelve TRUE si cualquiera de los datos es evaluado como TRUE
  • & solo devuelve TRUE si ambos datos son evaluados como TRUE
  • | solo devuelve FALSE si ambos datos son evaluados como FALSE
  • & devuelve FALSE si cualquiera de los datos es evaluado como FALSE

Además tenemos la función isTRUE() que comprueba si un valor es TRUE.

FunciónOperaciónEjemploResultado
isTRUE(a)es verdadero, afirmaciónisTRUE(TRUE)TRUE

6.3.1 Operadores lógicos y evaluación de expresiones

En un sentido estricto, al usar estos operadores estamos combinando dos valor booleanos, pero una forma de entender estos operadores es que evaluan la veracidad (“truthiness”, en inglés) de dos objetos al mismo tiempo.

Cuando nuestros objetos son datos son de tipo lógico, esta evaluación es muy transparente, TRUE | FALSE nos devuelve TRUE mientras que TRUE | FALSE nos devuelve TRUE. Sin embargo, como podemos usar estos operadores con cualquier tipo de datos, estos primero se evaluan a TRUE or FALSE y lo mismo es cierto para el resultado de otras operaciones o funciones.

Para explicar esto un poco más, supongamos que tenemos dos mascotas, una llamada Menchi y la otra Tlaloc, que tienen los atributos que se muestran en la siguiente tabla.

AtributoMenchi 🐕Tlaloc 🐈
ClaseMamíferoMamífero
EspeciePerroGato
SexoHembraMacho
Número de patas44
PelajeCortoLargo

Vamos a evaluar algunas afirmaciones sobre Menchi y Tlaloc.

  • Menchi Y (&) Tlaloc son Mamíferos

Tenemos que evaluar el atributo “Clase” de cada uno de ellos

  • ¿La Clase de Menchi es Mamifero? Verdadero (TRUE)
  • ¿La Clase de Tlaloc es Mamifero? Verdadero (TRUE)

Entonces:

  • Menchi == TRUE
  • Tlaloc == TRUE

Que podríamos representar así:

  • TRUE & TRUE

Que nos da como resultado TRUE. Es decir, es Verdadero que Menchi y Tlaloc son Mamíferos.

Evaluémos una segunda afirmación:

  • Menchi Y (&) Tlaloc son Perros

De nuevo, evaluamos el atributo correspondiente de ambos:

  • ¿La Especie de Menchi es Perro? Verdadero (TRUE)
  • ¿La Especie de Tlaloc es Gato? Falso (FALSE)

Entonces:

  • Menchi == TRUE
  • Tlaloc == FALSE

Y, por lo tanto:

  • TRUE & FALSE

Que nos da como resultado FALSE. Es decir, es Falso que Menchi y Tlaloc son Perros.

Cambiemos nuestra afirmación:

  • Menchi O (|) Tlaloc son Perros

No suena muy natural si lo decimos de esta manera. Cambiemos la formulación:

  • Menchi O (|) Tlaloc es un Perro

Como ya vimos, para que el operador | (O, OR) devuelva TRUE, basta con que cualquier elementos sea TRUE, así que podemos expresar esta afirmación de esta manera.

Ya conocemos el resultado de evaluar el atributo Especia de Menchi y Tlaloc.

  • Menchi == TRUE
  • Tlaloc == FALSE

Por lo tanto:

  • TRUE | FALSE

Que nos da como resultado TRUE. Es decir, es Verdadero que Menchi o Tlaloc es un Perro.

Finalmente, tenemos una afirmación que usa ! (NO, NOT).

  • Menchi No (!) es Macho

En este ejemplo, esta afirmación es fácil de evaluar, pues sólo tenemos que mirar el atributo correspondiente para llegar al resultado TRUE, es Verdadero que Menchi No es Macho.

Pero podemos combinar esta afirmación otra, sobre Tlaloc.

  • Menchi No (!) es Macho Y (&) Tlaloc es Macho

Sabemos que es Verdadero que Tlaloc es Macho, por lo tanto:

  • TRUE & TRUE

Que nos da como resultado TRUE, es Verdadero que Menchi No es Macho y Tlaloc es Macho.

Aun hay otras que puedes intentar identificar como ejercicio con las características de Menchi y Tlaloc. Además este último ejemplo es una pequeña muestra de lo complejas que pueden ser las operaciones lógicas y en la siguiente sección veremos cómo se combinan con operaciones relacionales.

6.3.2 Operadores lógicos con operadores relacionales

Podemos combinar los operadores lógicos con operadores relacionales para evaluar expresiones complejas.

Como el resultado de una operación relacional es TRUE or FALSE, podemos evaluar expresiones como la siguiente.

(4 < 6) & (6 > 4)
[1] TRUE

Obtenemos como resultado TRUE, porque ambos elementos son verdaderos.

4 < 6
[1] TRUE
6 > 4
[1] TRUE

Por supuesto, podemos tener expresiones con datos no numéricos y operadores relacionales.

("Pluma" == "Lápiz") | ("Lápiz" != "Hoja")
[1] TRUE

Obtenemos TRUE porque al menos uno de los dos elementos es verdadero.

"Pluma" == "Lápiz"
[1] FALSE
"Lápiz" != "Hoja"
[1] TRUE

Hemos usado paréntesis para establecer el orden en que deben ocurrir las operaciones, esto lo revisaremos en la ?sec-operadores-orden-operaciones de este mismo capítulo.

6.3.3 Operadores lógicos con datos enteros y numéricos

Los datos enteros y numéricos pueden ser coercionados a lógicos. Todos los valores enteros y numéricos distintos a 0 son coercionados a TRUE, mientras que 0 siempre es coercionado a FALSE.

Por ejemplo, 5 | 0 devuelve TRUE porque el número 5 es coercionado a TRUE y 0 es conercionado a `FALSE.

5 | 0
[1] TRUE

Podemos comprobar lo anterior con la función isTRUE().

isTRUE(0)
[1] FALSE
isTRUE(5)
[1] FALSE

Por lo tanto, 5 | FALSE devuelve TRUE y 0 & TRUE devuelve FALSE.

5 | FALSE
[1] TRUE
0 & FALSE
[1] FALSE

6.3.4 Operadores lógicos con cadenas de texto

Si intentamos una operación lógica con una cadena de texto obtenemos siempre un error.

"TRUE" & FALSE
Error in "TRUE" & FALSE: operations are possible only for numeric, logical or complex types

"FALSE" | TRUE
Error in "FALSE" | TRUE: operations are possible only for numeric, logical or complex types

"a" | FALSE
Error in "a" | FALSE: operations are possible only for numeric, logical or complex types

"Z" & TRUE
Error in "Z" & TRUE: operations are possible only for numeric, logical or complex types

!"casa"
Error in !"casa": invalid argument type

6.3.5 Operadores lógicos con NA y NULL

Al usar el operador | (OR), si cualquiera de los datos es TRUE, obtenemos TRUE aunque el otro dato sea NA.

NA | TRUE
[1] TRUE

Pero si un dato es NA y el otro es FALSE, obtenemos NA.

NA | FALSE
[1] NA

Y si un dato es NULL obtenemos un vector lógico vacío.

NULL | FALSE
logical(0)

Para el caso de & (AND), si uno de los datos es NA y el otro es TRUE obtenemos NA, y si el otro es FALSE obtenemos False.

NA & TRUE
[1] NA
NA & FALSE
[1] FALSE

Si uno es de los datos es NULL, obtenemos un vector lógico vacío.

NULL & TRUE
logical(0)
NULL & FALSE
logical(0)

Si negamos NA con ! (NOT) obtenemos NA.

!NA
[1] NA

Pero si negamos NULL se nos devuelve un error.

!NULL
Error in !NULL: invalid argument type

6.4 Operadores de asignación

Este es probablemente el tipo de operador más importante de todos porque nos permite asignar datos y funciones a variables para después trabajar con ellas.

Estos operadores asignan el valor que se encuentra a su derecha a la variable que se encuentra a su izquierda.

OperadorOperación
<-Asigna un valor a una variable
=Asigna un valor a una variable

A lo largo de este libro utilizaremos <- para asignaciones por ser característico de R y el que más frecuentemente encontraremos en código de otras personas. Además, tiene la ventaja de que es muy expresivo visualmente.

Veamos una asignación. Asignaremos el valor 1 a la variable uno.

uno <- 1

Si llamamos a la variable uno nos es devuelto el valor que tiene asignado.

uno
[1] 1

Después de realizar la operación de asignación podemos usar el nombre de la variable para realizar operaciones con ella, como si fuera del tipo de datos que le hemos asignado. Si asignamos un valor a una variable a la que ya habíamos asignado datos, nuestra variable conservará el valor más reciente.

Esta operación también nos permite “guardar” el resultado de operaciones, de modo que los podemos recuperar sin necesidad de ejecutar las operaciones otra vez. Es suficiente llamar el nombre de la variable para que nos devuelva los valores que ha “guardado”.

Ahora asignaremos valores numéricos a las variables estatura y peso.

estatura <- 1.73
peso <- 83

Llamamos a las variables para que nos sean devueltos sus valores asignados.

estatura
[1] 1.73

peso
[1] 83

Ahora podemos usar estas variables para realizar operaciones. Dividimos peso entre estatura elevada al cuadrado.

peso / estatura ^ 2
[1] 27.7323

Cambiamos el valor de una variable a uno nuevo y realizamos operaciones, mostrando que se ha conservado el último valor asignado a ellas.

peso <- 76

peso
[1] 76

peso / estatura ^ 2
[1] 25.39343

estatura <- 1.56
peso <- 48

peso / estatura ^ 2
[1] 19.72387

También podemos asignar el resultado de una operación a una variable nueva, en este caso una llamada imc, por “índice de masa corporal”.

imc <- peso / estatura ^ 2

imc
[1] 19.72387

De esta manera ya tenemos una forma sencilla para calcular el índice de masa corporal de una persona.

También podemos observar que es posible asignarle a una variable los valores de otra variable o el resultado de operaciones hechas con otras variables, lo cual nos abre la posibilidad de operaciones complejas.

Veamos otro ejemplo, en el que hacemos varias operaciones para obtener el valor de rapidez.

velocidad_inicial <- 110
velocidad_final <- 185

tiempo_inicial <- 0
tiempo_final <- 15

variacion_velocidad <- velocidad_final - velocidad_inicial
variacion_tiempo <- tiempo_final - tiempo_inicial

rapidez <- variacion_velocidad / variacion_tiempo

rapidez
[1] 5

Por supuesto, podemos asignar NA o NULL a variables.

variable_na <- NA
variable_na
[1] NA

variable_null <- NULL
variable_null
NULL

No podemos asignar un valor a valor, si lo intentamos nos es devuelto un error.

33 <- TRUE
Error in 33 <- TRUE: invalid (do_set) left-hand side to assignment

TRUE <- 77
Error in TRUE <- 77: invalid (do_set) left-hand side to assignment

NA <- 94.1
Error in NA <- 94.1: invalid (do_set) left-hand side to assignment

Sin embargo, si intentamos asignar un valor a una cadena de texto, no se nos devuelve un error ni una advertencia.

"variable_texto" <- 512

Pero si llamamos a "variable_texto" nos es devuelto "variable_texto".

"variable_texto"
[1] "variable_texto"

¿Qué ha ocurrido?

En realidad, la asignación sí ha ocurrido, pero a una variable llamada variable_texto, no a la cadena de texto.

variable_texto
[1] 512

Esto se debe a la forma en que R evalúa los nombres de variables y explicarlo va más allá del alcance de un texto para principiantes, así que sólo recordemos que este comportamiento inesperado existe para evitarnos sorpresas en el futuro.

6.5 Orden de operaciones

En R, al igual que en matemáticas, las operaciones tienen un orden o jerarquía de evaluación definido. Cuanto tenemos varias operaciones en una misma expresión, estas no ocurren todas al mismo tiempo, sino en secuencia.

En la siguiente tabla se presenta el orden en que ocurren las operaciones que hemos revisado en este capítulo.

OrdenOperación
1^
2* /
3+ -
4< > <= >= == !=
5!
6&
7|
8<-

Si tenemos el mismo operador varias veces en una misma expresión, estos se evalúan de izquierda a derecha.

En el siguiente ejemplo, primero se resta 10 a 20 y después 5 al resultado de esa operación.

20 - 10 - 5
[1] 5

Si agregamos una multiplicación a la expresión, primero ocurre la multiplicación de 10 por 5, después la resta de 20 menos su resultado y, finalmente, el resultado de esa operación menos 5.

20 - 10 * 2 - 5
[1] -5

Si en una misma expresión tenemos una multiplicación (*) y una división (/), se evalúan de izquieda a derecha.

En este ejemplo, primero la multiplicación y después de la división.

4 * 3 / 2
[1] 6

Y en este ejemplo, primero la división y luego la multiplicación.

4 / 3 * 2
[1] 2.666667

Lo mismo aplica para la suma (+) y la resta (-).

Primero la suma y después de la resta.

4 + 3 - 2
[1] 5

Primero la resta y después la suma.

4 - 3 + 2
[1] 3

En el caso de los operadores de comparación, si una expresión tiene más de un símbolo de este tipo, nos es devuelto un error, a menos que usemos paréntesis.

23 > 26 == 28

Error in parse(text = input): <text>:1:9: unexpected '=='
1: 23 > 26 ==

El orden de evaluación de los operadores lógicos puede ser un poco desafiante al principio, como en expresiones como la siguiente.

FALSE | FALSE & TRUE & TRUE | TRUE

Pero si recordamos el orden de operaciones y que símbolos iguales se evalúan de izquierda a derecha, podemos anticipar que el resultado final es TRUE, porque:

  1. FALSE & TRUE es FALSE, entonces
  2. FALSE & TRUE es FALSE, entonces
  3. FALSE | FALSE es FALSE, entonces
  4. FALSE | TRUE es TRUE

Comprobemos lo anterior.

FALSE | FALSE & TRUE & TRUE | TRUE
[1] TRUE

Por supuesto, podemos usar paréntesis para facilitar la lectura, además de para establecer un orden de operación propio.

6.5.1 Paréntesis

Si deseamos que una operación ocurra antes que otra, rompiendo el orden definido de evaluación, o para hacerla la más fácil de leer, usamos paréntesis.

En el orden de operaciones definido, ocurre primero la multiplicación y después suma

1 * 2 + 3
[1] 5

Si encerramos entre paréntesis la suma, esta ocurrira primero y después la multiplicación

1 * (2 + 3)
[1] 5

También podemos usar paréntesis anidados, de este modo las operaciones ocurrirán del paréntesis con el nivel más profundo de anidación, hacia el nivel menos profundo.

  • (((ocurre_primero)ocurre_segundo)ocurre_tercero)

En la siguiente expresión, se sigue el orden de operaciones regular: primero la resta, después la multiplicación y finalmente la potencia.

2 * 4 - 5 ^ 3
[1] -117

Con los paréntesis anidados, indicamos que ocurra primero la resta, el nivel más profundo de anidación, después la multiplicación, y finalmente la potencia, el nivel menos profundo de anidación.

((2 * (4 - 5)) ^ 4)
[1] 16

Podemos cambiar cómo anidamos los paréntesis, para que primero ocurra la potencia, después la resta y finalmente la multiplicación.

(2 * (4 - (5 ^ 3)))
[1] -242

Si tenemos paréntesis tanto en el lado izquierdo como en el derecho de una operador, las operaciones dentro de los paréntesis son evaluadas primero y después las operaciones fuera de ellos.

(4 - 2) * (8 - 4)
[1] 8
(4 / 2) ^ (8 / 4)
[1] 4

Este ha sido un artículo largo, pero los operadores es un aspecto fundamental para escribir código, no solo en R, sino en cualquier lenguaje de programación, por lo que vale la pena dedicar tiempo para comprenderlos.


Comentarios

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *