Funciones en la programación R (con ejemplo)

¿Qué es una función en R?

Una función , en un entorno de programación, es un conjunto de instrucciones. Un programador crea una función para evitar repetir la misma tarea o reducir la complejidad.

Una función debe ser

  • escrito para llevar a cabo una determinada tarea
  • puede o no puede incluir argumentos
  • contener un cuerpo
  • puede o no devolver uno o más valores.

Un enfoque general para una función es usar la parte del argumento como entradas , alimentar la parte del cuerpo y finalmente devolver una salida . La sintaxis de una función es la siguiente:

function (arglist) {#Function body}

En este tutorial, aprenderemos

  • R importantes funciones integradas
  • Funciones generales
  • Funciones matemáticas
  • Funciones estadísticas
  • Escribir función en R
  • ¿Cuándo deberíamos escribir la función?
  • Funciones con condición

R importantes funciones integradas

Hay muchas funciones integradas en R. R empareja sus parámetros de entrada con sus argumentos de función, ya sea por valor o por posición, luego ejecuta el cuerpo de la función. Los argumentos de la función pueden tener valores predeterminados: si no especifica estos argumentos, R tomará el valor predeterminado.

Nota : Es posible ver el código fuente de una función ejecutando el nombre de la función en la consola.

Veremos tres grupos de funciones en acción.

  • Función general
  • Función matemática
  • Función estadística

Funciones generales

Ya estamos familiarizados con funciones generales como las funciones cbind (), rbind (), range (), sort (), order (). Cada una de estas funciones tiene una tarea específica, toma argumentos para devolver una salida. Las siguientes son funciones importantes que uno debe conocer:

función diff ()

Si trabaja en series de tiempo , necesita estacionar la serie tomando sus valores de retraso . Un proceso estacionario permite una media, varianza y autocorrelación constantes a lo largo del tiempo. Esto mejora principalmente la predicción de una serie temporal. Se puede hacer fácilmente con la función diff (). Podemos construir una serie de datos aleatoria con una tendencia y luego usar la función diff () para estacionar la serie. La función diff () acepta un argumento, un vector, y devuelve una diferencia rezagada e iterada adecuada.

Nota : a menudo necesitamos crear datos aleatorios, pero para el aprendizaje y la comparación queremos que los números sean idénticos en todas las máquinas. Para asegurarnos de que todos generamos los mismos datos, usamos la función set.seed () con valores arbitrarios de 123. La función set.seed () se genera a través del proceso del generador de números pseudoaleatorios que hace que todas las computadoras modernas tengan la misma secuencia. de números. Si no usamos la función set.seed (), todos tendremos diferentes secuencias de números.

set.seed(123)## Create the datax = rnorm(1000)ts <- cumsum(x)## Stationary the seriediff_ts <- diff(ts)par(mfrow=c(1,2))## Plot the seriesplot(ts,)plot(diff(ts),)

función length ()

En muchos casos, queremos saber la longitud de un vector para el cálculo o para usarlo en un bucle for. La función length () cuenta el número de filas en el vector x. Los siguientes códigos importan el conjunto de datos de automóviles y devuelven el número de filas.

Nota : length () devuelve el número de elementos de un vector. Si la función se pasa a una matriz o un marco de datos, se devuelve el número de columnas.

dt <- cars## number columnslength(dt)

Producción:

## [1] 1
## number rowslength(dt[,1])

Producción:

## [1] 50

Funciones matemáticas

R tiene una serie de funciones matemáticas.

Operador Descripción
abs (x) Toma el valor absoluto de x
log (x, base = y) Toma el logaritmo de x con base y; si no se especifica la base, devuelve el logaritmo natural
exp (x) Devuelve el exponencial de x
sqrt (x) Devuelve la raíz cuadrada de x
factorial (x) Devuelve el factorial de x (x!)
# sequence of number from 44 to 55 both including incremented by 1x_vector <- seq(45,55, by = 1)#logarithmlog(x_vector)

Producción:

## [1] 3.806662 3.828641 3.850148 3.871201 3.891820 3.912023 3.931826## [8] 3.951244 3.970292 3.988984 4.007333
#exponentialexp(x_vector)
#squared rootsqrt(x_vector)

Producción:

## [1] 6.708204 6.782330 6.855655 6.928203 7.000000 7.071068 7.141428## [8] 7.211103 7.280110 7.348469 7.416198
#factorialfactorial(x_vector)

Producción:

## [1] 1.196222e+56 5.502622e+57 2.586232e+59 1.241392e+61 6.082819e+62## [6] 3.041409e+64 1.551119e+66 8.065818e+67 4.274883e+69 2.308437e+71## [11] 1.269640e+73

Funciones estadísticas

La instalación estándar R contiene una amplia gama de funciones estadísticas. En este tutorial, veremos brevemente la función más importante ...

Funciones estadísticas básicas

Operador

Descripción

media (x)

Media de x

mediana (x)

Mediana de x

var (x)

Varianza de x

sd (x)

Desviación estándar de x

escala (x)

Puntuaciones estándar (puntuaciones z) de x

cuantil (x)

Los cuartiles de x

resumen (x)

Resumen de x: media, mínima, máxima, etc.

speed <- dt$speedspeed# Mean speed of cars datasetmean(speed)

Producción:

## [1] 15.4
# Median speed of cars datasetmedian(speed)

Producción:

## [1] 15
# Variance speed of cars datasetvar(speed)

Producción:

## [1] 27.95918
# Standard deviation speed of cars datasetsd(speed)

Producción:

## [1] 5.287644
# Standardize vector speed of cars datasethead(scale(speed), 5)

Producción:

## [,1]## [1,] -2.155969## [2,] -2.155969## [3,] -1.588609## [4,] -1.588609## [5,] -1.399489
# Quantile speed of cars datasetquantile(speed)

Producción:

## 0% 25% 50% 75% 100%## 4 12 15 19 25
# Summary speed of cars datasetsummary(speed)

Producción:

## Min. 1st Qu. Median Mean 3rd Qu. Max.## 4.0 12.0 15.0 15.4 19.0 25.0

Hasta este punto, hemos aprendido muchas funciones integradas de R.

Nota : tenga cuidado con la clase del argumento, es decir, numérico, booleano o de cadena. Por ejemplo, si necesitamos pasar un valor de cadena, debemos encerrar la cadena entre comillas: "ABC".

Escribir función en R

En alguna ocasión, necesitamos escribir nuestra propia función porque tenemos que realizar una tarea en particular y no existe ninguna función ya preparada. Una función definida por el usuario incluye un nombre , argumentos y un cuerpo .

function.name <- function(arguments){computations on the argumentssome other code}

Nota : una buena práctica es nombrar una función definida por el usuario diferente de una función incorporada. Evita confusiones.

Función de un argumento

En el siguiente fragmento, definimos una función cuadrada simple. La función acepta un valor y devuelve el cuadrado del valor.

square_function<- function(n){# compute the square of integer `n`n^2}# calling the function and passing value 4square_function(4)

Explicación del código:

  • La función se llama función_cuadrada; se puede llamar como queramos.
  • Recibe un argumento "n". No especificamos el tipo de variable para que el usuario pueda pasar un número entero, un vector o una matriz
  • La función toma la entrada "n" y devuelve el cuadrado de la entrada.

    Cuando haya terminado de usar la función, podemos eliminarla con la función rm ().

# después de crear la función

rm(square_function)square_function

En la consola, podemos ver un mensaje de error: Error: el objeto 'función_cuadrada' no encontrado indica que la función no existe.

Alcance del medio ambiente

En R, el entorno es una colección de objetos como funciones, variables, marco de datos, etc.

R abre un entorno cada vez que se solicita Rstudio.

El entorno de nivel superior disponible es el entorno global , llamado R_GlobalEnv. Y tenemos el entorno local.

Podemos enumerar el contenido del entorno actual.

ls(environment())

Producción

## [1] "diff_ts" "dt" "speed" "square_function"## [5] "ts" "x" "x_vector"

Puede ver todas las variables y funciones creadas en R_GlobalEnv.

La lista anterior variará según el código histórico que ejecute en R Studio.

Tenga en cuenta que n, el argumento de la función función_cuadrada no se encuentra en este entorno global .

Se crea un nuevo entorno para cada función. En el ejemplo anterior, la función square_function () crea un nuevo entorno dentro del entorno global.

Para aclarar la diferencia entre el entorno global y local , estudiemos el siguiente ejemplo

Esta función toma un valor x como argumento y lo agrega ay define fuera y dentro de la función

La función f devuelve el resultado 15. Esto se debe a que y se define en el entorno global. Cualquier variable definida en el entorno global se puede utilizar localmente. La variable y tiene el valor de 10 durante todas las llamadas a funciones y es accesible en cualquier momento.

Veamos qué pasa si la variable y está definida dentro de la función.

Necesitamos soltar `y` antes de ejecutar este código usando rm r

La salida también es 15 cuando llamamos a f (5) pero devuelve un error cuando intentamos imprimir el valor y. La variable y no se encuentra en el entorno global.

Finalmente, R usa la definición de variable más reciente para pasar dentro del cuerpo de una función. Consideremos el siguiente ejemplo:

R ignora los valores y definidos fuera de la función porque creamos explícitamente una variable ay dentro del cuerpo de la función.

Función de argumentos múltiples

Podemos escribir una función con más de un argumento. Considere la función llamada "tiempos". Es una función sencilla que multiplica dos variables.

times <- function(x,y) {x*y}times(2,4)

Producción:

## [1] 8

¿Cuándo deberíamos escribir la función?

Los científicos de datos deben realizar muchas tareas repetitivas. La mayoría de las veces, copiamos y pegamos fragmentos de código de forma repetitiva. Por ejemplo, se recomienda encarecidamente la normalización de una variable antes de ejecutar un algoritmo de aprendizaje automático. La fórmula para normalizar una variable es:

Ya sabemos cómo usar la función min () y max () en R. Usamos la biblioteca tibble para crear el marco de datos. Tibble es hasta ahora la función más conveniente para crear un conjunto de datos desde cero.

library(tibble)# Create a data framedata_frame <- tibble(c1 = rnorm(50, 5, 1.5),c2 = rnorm(50, 5, 1.5),c3 = rnorm(50, 5, 1.5),)

Procederemos en dos pasos para calcular la función descrita anteriormente. En el primer paso, crearemos una variable llamada c1_norm que es el cambio de escala de c1. En el paso dos, simplemente copiamos y pegamos el código de c1_norm y lo cambiamos con c2 y c3.

Detalle de la función con la columna c1:

Nominador:: marco_datos $ c1 -min (marco_datos $ c1))

Denominador: max (data_frame $ c1) -min (data_frame $ c1))

Por lo tanto, podemos dividirlos para obtener el valor normalizado de la columna c1:

(data_frame$c1 -min(data_frame$c1))/(max(data_frame$c1)-min(data_frame$c1)) 

Podemos crear c1_norm, c2_norm y c3_norm:

Create c1_norm: rescaling of c1data_frame$c1_norm <- (data_frame$c1 -min(data_frame$c1))/(max(data_frame$c1)-min(data_frame$c1))# show the first five valueshead(data_frame$c1_norm, 5)

Producción:

## [1] 0.3400113 0.4198788 0.8524394 0.4925860 0.5067991

Funciona. Podemos copiar y pegar

data_frame$c1_norm <- (data_frame$c1 -min(data_frame$c1))/(max(data_frame$c1)-min(data_frame$c1))

luego cambie c1_norm a c2_norm y c1 a c2. Hacemos lo mismo para crear c3_norm

data_frame$c2_norm <- (data_frame$c2 - min(data_frame$c2))/(max(data_frame$c2)-min(data_frame$c2))data_frame$c3_norm <- (data_frame$c3 - min(data_frame$c3))/(max(data_frame$c3)-min(data_frame$c3))

Reescalamos perfectamente las variables c1, c2 y c3.

Sin embargo, este método tiende a equivocarse. Podríamos copiar y olvidar cambiar el nombre de la columna después de pegar. Por lo tanto, una buena práctica es escribir una función cada vez que necesite pegar el mismo código más de dos veces. Podemos reorganizar el código en una fórmula y llamarlo cuando sea necesario. Para escribir nuestra propia función, necesitamos dar:

  • Nombre: normalizar.
  • el número de argumentos: solo necesitamos un argumento, que es la columna que usamos en nuestro cálculo.
  • El cuerpo: esta es simplemente la fórmula que queremos devolver.

Procederemos paso a paso para crear la función normalizar.

Paso 1) Creamos el nominador , que es. En R, podemos almacenar el nominador en una variable como esta:

nominator <- x-min(x)

Paso 2) se calcula el denominador: . Podemos replicar la idea del paso 1 y almacenar el cálculo en una variable:

denominator <- max(x)-min(x)

Paso 3) Realizamos la división entre el nominador y el denominador.

normalize <- nominator/denominator

Paso 4) Para devolver valor a la función de llamada, debemos pasar normalizar dentro de return () para obtener la salida de la función.

return(normalize)

Paso 5) Estamos listos para usar la función envolviendo todo dentro del soporte.

normalize <- function(x){# step 1: create the nominatornominator <- x-min(x)# step 2: create the denominatordenominator <- max(x)-min(x)# step 3: divide nominator by denominatornormalize <- nominator/denominator# return the valuereturn(normalize)}

Probemos nuestra función con la variable c1:

normalize(data_frame$c1)

Funciona perfectamente. Creamos nuestra primera función.

Las funciones son una forma más completa de realizar una tarea repetitiva. Podemos usar la fórmula de normalización en diferentes columnas, como a continuación:

data_frame$c1_norm_function <- normalize (data_frame$c1)data_frame$c2_norm_function <- normalize (data_frame$c2)data_frame$c3_norm_function <- normalize (data_frame$c3)

Aunque el ejemplo es simple, podemos inferir el poder de una fórmula. El código anterior es más fácil de leer y especialmente evita errores al pegar códigos.

Funciones con condición

A veces, necesitamos incluir condiciones en una función para permitir que el código devuelva diferentes salidas.

En las tareas de Machine Learning, necesitamos dividir el conjunto de datos entre un conjunto de trenes y un conjunto de prueba. El conjunto de trenes permite que el algoritmo aprenda de los datos. Para probar el rendimiento de nuestro modelo, podemos usar el conjunto de prueba para devolver la medida de rendimiento. R no tiene una función para crear dos conjuntos de datos. Podemos escribir nuestra propia función para hacer eso. Nuestra función toma dos argumentos y se llama split_data (). La idea detrás es simple, multiplicamos la longitud del conjunto de datos (es decir, el número de observaciones) por 0,8. Por ejemplo, si queremos dividir el conjunto de datos 80/20, y nuestro conjunto de datos contiene 100 filas, entonces nuestra función multiplicará 0.8 * 100 = 80. Se seleccionarán 80 filas para convertirse en nuestros datos de entrenamiento.

Usaremos el conjunto de datos de calidad del aire para probar nuestra función definida por el usuario. El conjunto de datos de calidad del aire tiene 153 filas. Lo podemos ver con el siguiente código:

nrow(airquality)

Producción:

## [1] 153 

Procederemos de la siguiente manera:

split_data <- function(df, train = TRUE)Arguments:-df: Define the dataset-train: Specify if the function returns the train set or test set. By default, set to TRUE

Nuestra función tiene dos argumentos. El tren de argumentos es un parámetro booleano. Si se establece en TRUE, nuestra función crea el conjunto de datos del tren; de lo contrario, crea el conjunto de datos de prueba.

Podemos proceder como lo hicimos con la función normalize (). Escribimos el código como si fuera solo un código de una sola vez y luego envolvemos todo con la condición en el cuerpo para crear la función.

Paso 1:

Necesitamos calcular la longitud del conjunto de datos. Esto se hace con la función nrow (). Nrow devuelve el número total de filas del conjunto de datos. Llamamos longitud variable.

length<- nrow(airquality)length

Producción:

## [1] 153

Paso 2:

Multiplicamos la longitud por 0,8. Devolverá el número de filas para seleccionar. Debería ser 153 * 0.8 = 122.4

total_row <- length*0.8total_row

Producción:

## [1] 122.4

Queremos seleccionar 122 filas entre las 153 filas del conjunto de datos de calidad del aire. Creamos una lista que contiene valores de 1 a total_row. Almacenamos el resultado en la variable llamada split

split <- 1:total_rowsplit[1:5] 

Producción:

## [1] 1 2 3 4 5

split elige las primeras 122 filas del conjunto de datos. Por ejemplo, podemos ver que nuestra división de variables reúne el valor 1, 2, 3, 4, 5 y así sucesivamente. Estos valores serán el índice cuando seleccionemos las filas a devolver.

Paso 3:

Necesitamos seleccionar las filas en el conjunto de datos de calidad del aire en función de los valores almacenados en la variable de división. Esto se hace así:

train_df <- airquality[split, ]head(train_df)

Producción:

##[1] Ozone Solar.R Wind Temp Month Day##[2] 51 13 137 10.3 76 6 20##[3] 15 18 65 13.2 58 5 15##[4] 64 32 236 9.2 81 7 3##[5] 27 NA NA 8.0 57 5 27##[6] 58 NA 47 10.3 73 6 27##[7] 44 23 148 8.0 82 6 13

Paso 4:

Podemos crear el conjunto de datos de prueba usando las filas restantes, 123: 153. Esto se hace usando - delante de split.

test_df <- airquality[-split, ]head(test_df)

Producción:

##[1] Ozone Solar.R Wind Temp Month Day##[2] 123 85 188 6.3 94 8 31##[3] 124 96 167 6.9 91 9 1##[4] 125 78 197 5.1 92 9 2##[5] 126 73 183 2.8 93 9 3##[6] 127 91 189 4.6 93 9 4##[7] 128 47 95 7.4 87 9 5

Paso 5:

Podemos crear la condición dentro del cuerpo de la función. Recuerde, tenemos un tren de argumentos que es un conjunto booleano en TRUE por defecto para devolver el conjunto de trenes. Para crear la condición, usamos la sintaxis if:

if (train ==TRUE){train_df <- airquality[split, ]return(train)} else {test_df <- airquality[-split, ]return(test)}

Esto es todo, podemos escribir la función. Solo necesitamos cambiar airquality a df porque queremos probar nuestra función en cualquier marco de datos, no solo airquality:

split_data <- function(df, train = TRUE){length<- nrow(df)total_row <- length *0.8split <- 1:total_rowif (train ==TRUE){train_df <- df[split, ]return(train_df)} else {test_df <- df[-split, ]return(test_df)}}

Probemos nuestra función en el conjunto de datos de calidad del aire. deberíamos tener un juego de trenes con 122 filas y un juego de prueba con 31 filas.

train <- split_data(airquality, train = TRUE)dim(train)

Producción:

## [1] 122 6
test <- split_data(airquality, train = FALSE)dim(test)

Producción:

## [1] 31 6

Articulos interesantes...