3.5: Uso de funciones para hacer cálculos
- Page ID
- 151343
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)
( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\id}{\mathrm{id}}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\kernel}{\mathrm{null}\,}\)
\( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\)
\( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\)
\( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)
\( \newcommand{\vectorA}[1]{\vec{#1}} % arrow\)
\( \newcommand{\vectorAt}[1]{\vec{\text{#1}}} % arrow\)
\( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vectorC}[1]{\textbf{#1}} \)
\( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)
\( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)
\( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\(\newcommand{\avec}{\mathbf a}\) \(\newcommand{\bvec}{\mathbf b}\) \(\newcommand{\cvec}{\mathbf c}\) \(\newcommand{\dvec}{\mathbf d}\) \(\newcommand{\dtil}{\widetilde{\mathbf d}}\) \(\newcommand{\evec}{\mathbf e}\) \(\newcommand{\fvec}{\mathbf f}\) \(\newcommand{\nvec}{\mathbf n}\) \(\newcommand{\pvec}{\mathbf p}\) \(\newcommand{\qvec}{\mathbf q}\) \(\newcommand{\svec}{\mathbf s}\) \(\newcommand{\tvec}{\mathbf t}\) \(\newcommand{\uvec}{\mathbf u}\) \(\newcommand{\vvec}{\mathbf v}\) \(\newcommand{\wvec}{\mathbf w}\) \(\newcommand{\xvec}{\mathbf x}\) \(\newcommand{\yvec}{\mathbf y}\) \(\newcommand{\zvec}{\mathbf z}\) \(\newcommand{\rvec}{\mathbf r}\) \(\newcommand{\mvec}{\mathbf m}\) \(\newcommand{\zerovec}{\mathbf 0}\) \(\newcommand{\onevec}{\mathbf 1}\) \(\newcommand{\real}{\mathbb R}\) \(\newcommand{\twovec}[2]{\left[\begin{array}{r}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\ctwovec}[2]{\left[\begin{array}{c}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\threevec}[3]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\cthreevec}[3]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\fourvec}[4]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\cfourvec}[4]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\fivevec}[5]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\cfivevec}[5]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\mattwo}[4]{\left[\begin{array}{rr}#1 \amp #2 \\ #3 \amp #4 \\ \end{array}\right]}\) \(\newcommand{\laspan}[1]{\text{Span}\{#1\}}\) \(\newcommand{\bcal}{\cal B}\) \(\newcommand{\ccal}{\cal C}\) \(\newcommand{\scal}{\cal S}\) \(\newcommand{\wcal}{\cal W}\) \(\newcommand{\ecal}{\cal E}\) \(\newcommand{\coords}[2]{\left\{#1\right\}_{#2}}\) \(\newcommand{\gray}[1]{\color{gray}{#1}}\) \(\newcommand{\lgray}[1]{\color{lightgray}{#1}}\) \(\newcommand{\rank}{\operatorname{rank}}\) \(\newcommand{\row}{\text{Row}}\) \(\newcommand{\col}{\text{Col}}\) \(\renewcommand{\row}{\text{Row}}\) \(\newcommand{\nul}{\text{Nul}}\) \(\newcommand{\var}{\text{Var}}\) \(\newcommand{\corr}{\text{corr}}\) \(\newcommand{\len}[1]{\left|#1\right|}\) \(\newcommand{\bbar}{\overline{\bvec}}\) \(\newcommand{\bhat}{\widehat{\bvec}}\) \(\newcommand{\bperp}{\bvec^\perp}\) \(\newcommand{\xhat}{\widehat{\xvec}}\) \(\newcommand{\vhat}{\widehat{\vvec}}\) \(\newcommand{\uhat}{\widehat{\uvec}}\) \(\newcommand{\what}{\widehat{\wvec}}\) \(\newcommand{\Sighat}{\widehat{\Sigma}}\) \(\newcommand{\lt}{<}\) \(\newcommand{\gt}{>}\) \(\newcommand{\amp}{&}\) \(\definecolor{fillinmathshade}{gray}{0.9}\)Los símbolos +
, -
, *
y así sucesivamente son ejemplos de operadores. Como hemos visto, puedes hacer bastantes cálculos con solo usar estos operadores. Sin embargo, para hacer cálculos más avanzados (y posteriormente, hacer estadísticas reales), vas a necesitar comenzar a usar funciones. 29. Así 10+20
es equivalente a la llamada de función + (20, 30)
. No es sorprendente que nadie utilice esta versión. Porque eso sería una estupidez.] Hablaré con más detalle sobre las funciones y cómo funcionan en la Sección 8.4, pero por ahora solo vamos a sumergirnos y usar algunas. Para empezar, supongamos que quería tomar la raíz cuadrada de 225. La raíz cuadrada, en caso de que tus matemáticas de secundaria estén un poco oxidadas, es justo lo contrario de cuadrar un número. Entonces, por ejemplo, como “5 al cuadrado es 25” puedo decir que “5 es la raíz cuadrada de 25”. La notación habitual para esto es
√25=5
aunque a veces también lo verás escrito así 25 0.5 =5. Esta segunda forma de escribir es algo útil para “recordarte” el hecho matemático de que “raíz cuadrada de x” es en realidad lo mismo que “elevar x a la potencia de 0.5”. Personalmente, nunca he encontrado que esto sea terriblemente significativo psicológicamente, aunque tengo que admitir que es bastante conveniente matemáticamente. En fin, no es importante. Lo importante es que recuerdes lo que es una raíz cuadrada, ya que vamos a necesitarla más adelante.
Para calcular la raíz cuadrada de 25, puedo hacerlo en mi cabeza con bastante facilidad, ya que memorizaba mis tablas de multiplicación cuando era niño. Se hace más difícil cuando los números se hacen más grandes, y prácticamente imposible si no son números enteros. Aquí es donde algo como R viene muy útil. Digamos que quería calcular √225, la raíz cuadrada de 225. Hay dos formas en las que podría hacer esto usando R. En primer lugar, ya que la raíz cuadrada de 255 es lo mismo que elevar 225 a la potencia de 0.5, podría usar el operador eléctrico ^
, tal como lo hicimos antes:
225 ^ 0.5
## [1] 15
Sin embargo, hay una segunda forma de hacerlo, ya que R también proporciona una función de raíz cuadrada, sqrt ()
. Para calcular la raíz cuadrada de 255 usando esta función, lo que hago es insertar el número 225
entre paréntesis. Es decir, el comando que escribo es el siguiente:
sqrt( 225 )
## [1] 15
y como cabría esperar de nuestra discusión anterior, los espacios entre paréntesis son puramente cosméticos. Podría haber escrito sqrt (225)
o sqrt (225)
y obtener el mismo resultado. Cuando usamos una función para hacer algo, generalmente nos referimos a esto como llamar a la función, y los valores que escribimos en la función (puede haber más de uno) se denominan los argumentos de esa función.
Obviamente, la función sqrt ()
realmente no nos da ninguna funcionalidad nueva, ya que ya sabíamos hacer cálculos de raíz cuadrada usando el operador eléctrico ^
, aunque creo que se ve mejor cuando usamos sqrt ()
. Sin embargo, hay muchas otras funciones en R: de hecho, casi todo lo de interés de lo que voy a hablar en este libro es una función R de algún tipo. Por ejemplo, una función que necesitaremos usar en este libro es la función de valor absoluto. Comparada con la función de raíz cuadrada, es extremadamente simple: simplemente convierte números negativos en números positivos, y deja solos los números positivos. Matemáticamente, el valor absoluto de x está escrito |x| o a veces abs (x). Calcular valores absolutos en R es bastante sencillo, ya que R proporciona la función abs ()
que puedes usar para este propósito. Cuando le das de comer un número positivo...
abs( 21 )
## [1] 21
la función de valor absoluto no le hace nada en absoluto. Pero cuando le das un número negativo, escupe la versión positiva del mismo número, así:
abs( -13 )
## [1] 13
Con toda honestidad, no hay nada que haga la función de valor absoluto que no puedas hacer con solo mirar el número y borrar el signo menos si hay uno. Sin embargo, hay algunos lugares más adelante en el libro donde tenemos que usar valores absolutos, así que pensé que podría ser una buena idea explicar el significado del término desde el principio.
Antes de seguir adelante, vale la pena señalar que —de la misma manera que R nos permite juntar múltiples operaciones en un comando más largo, como 1 + 2*4
por ejemplo— también nos permite juntar funciones e incluso combinar funciones con operadores si así lo deseamos. Por ejemplo, el siguiente es un comando perfectamente legítimo:
sqrt( 1 + abs(-8) )
## [1] 3
Cuando R ejecuta este comando, comienza calculando el valor de abs (-8)
, lo que produce un valor intermedio de 8
. Una vez hecho esto, el comando simplifica a sqrt (1 + 8)
. Para resolver la raíz cuadrada 30 primero necesita sumar 1 + 8
para obtener 9
, momento en el que evalúa sqrt (9)
, y así finalmente genera un valor de 3
.
Argumentos de función, sus nombres y sus valores predeterminados
Hay dos cosas más bastante importantes que debes entender sobre cómo funcionan las funciones en R, y es el uso de argumentos “nombrados” y valores predeterminados” para los argumentos. No es sorprendente, eso no quiere decir que esta sea la última vez que oigamos sobre cómo funcionan las funciones, pero son las últimas cosas que desesperadamente necesitamos discutir para que comiences. Para entender de qué se tratan estos dos conceptos, voy a introducir otra función. La función round ()
se puede utilizar para redondear algún valor al número entero más cercano. Por ejemplo, podría escribir esto:
round( 3.1415 )
## [1] 3
Bastante sencillo, de verdad. No obstante, supongamos que solo quería redondearlo a dos decimales: es decir, quiero obtener 3.14
como salida. La función round ()
lo admite, al permitirle ingresar un segundo argumento a la función que especifica el número de decimales a los que desea redondear el número. En otras palabras, podría hacer esto:
round( 3.14165, 2 )
## [1] 3.14
Lo que sucede aquí es que he especificado dos argumentos: el primer argumento es el número que necesita ser redondeado (es decir, 3.1415
), el segundo argumento es el número de decimales a los que debe redondearse (es decir, 2
), y los dos argumentos son separados por una coma. En este sencillo ejemplo, es bastante fácil recordar cuál argumento viene primero y cuál viene segundo, pero para funciones más complicadas esto no es fácil. Afortunadamente, la mayoría de las funciones R hacen uso de nombres de argumentos. Para la función round ()
, por ejemplo, el número que necesita ser redondeado se especifica usando el argumento x
, y el número de puntos decimales a los que desea que se redondee se especifica usando el argumento de dígitos
. Debido a que tenemos estos nombres disponibles para nosotros, podemos especificar los argumentos a la función por nombre. Lo hacemos así:
round( x = 3.1415, digits = 2 )
## [1] 3.14
Observe que esto es algo similar en espíritu a la asignación de variables (Sección @ (asignar), excepto que usé =
aquí, en lugar de <-
. En ambos casos estamos especificando valores específicos para ser asociados a una etiqueta. Sin embargo, hay algunas diferencias entre lo que estaba haciendo antes al crear variables, y lo que estoy haciendo aquí al especificar argumentos, y así como consecuencia es importante que uses =
en este contexto.
Como puedes ver, especificar los argumentos por nombre implica mucho más mecanografiar, pero también es mucho más fácil de leer. Debido a esto, los comandos de este libro suelen especificar argumentos por nombre, 31 ya que eso te deja más claro lo que estoy haciendo. Sin embargo, una cosa importante a tener en cuenta es que al especificar los argumentos usando sus nombres, no importa en qué orden los escriba. Pero si no usas los nombres de los argumentos, entonces tienes que introducir los argumentos en el orden correcto. En otras palabras, estos tres comandos producen todos la misma salida...
round( 3.14165, 2 )
## [1] 3.14
round( x = 3.1415, digits = 2 )
## [1] 3.14
round( digits = 2, x = 3.1415 )
## [1] 3.14
pero éste no...
round( 2, 3.14165 )
## [1] 2
¿Cómo averiguas cuál es el orden correcto? Hay algunas formas diferentes, pero la más fácil es mirar la documentación de ayuda para la función (ver Sección 4.12. Sin embargo, si alguna vez no estás seguro, probablemente sea mejor escribir realmente el nombre del argumento.
Bien, entonces eso es lo primero que dije que necesitarías saber: los nombres de los argumentos. Lo segundo que debes saber son los valores predeterminados. Observe que la primera vez que llamé a la función round ()
en realidad no especificé el argumento de dígitos
en absoluto, y sin embargo, R de alguna manera sabía que esto significaba que debería redondear al número entero más cercano. ¿Cómo sucedió eso? La respuesta es que el argumento de dígitos
tiene un valor predeterminado de 0
, lo que significa que si decide no especificar un valor para dígitos
entonces R actuará como si hubiera escrito dígitos = 0
. Esto es bastante útil: la gran mayoría de las veces cuando quieres redondear un número quieres redondearlo al número entero más cercano, y sería bastante molesto tener que especificar el argumento de los dígitos
cada vez. Por otro lado, a veces realmente quieres redondear a algo que no sea el número entero más cercano, ¡y sería aún más molesto si R no permitiera esto! Así, al tener dígitos = 0
como valor predeterminado, obtenemos lo mejor de ambos mundos.