Funções na programação R com exemplo

O que é uma função em R?

A função, em um ambiente de programação, é um conjunto de instruções. Um programador constrói uma função para evitar repetindo o mesma tarefa ou reduzir complexity.

Uma função deve ser

  • escrito para realizar uma tarefa específica
  • pode ou não incluir argumentos
  • contém um corpo
  • pode ou não retornar um ou mais valores.

Uma abordagem geral para uma função é usar a parte do argumento como inputs, alimente o corpo parte e finalmente retornar um saída. A sintaxe de uma função é a seguintewing:

function (arglist)  {
  #Function body
}

R funções integradas importantes

Existem muitas funções integradas em R. R combina seus parâmetros de entrada com seus argumentos de função, por valor ou por posição, e então executa o corpo da função. Os argumentos da função podem ter valores padrão: se você não especificar esses argumentos, R assumirá o valor padrão.
Note:
É possível ver o código fonte de uma função executando o nome da própria função no console.

R Funções integradas importantes

Veremos três grupos de funções em ação

  • Função geral
  • Função matemática
  • Função estatística

Funções gerais

Já estamos familiarizados com funções gerais como funções cbind(), rbind(),range(),sort(),order(). Cada uma dessas funções possui uma tarefa específica, recebe argumentos para retornar uma saída. Sigawing são funções importantes que devemos conhecer

função diff()

Se você trabalhar em série temporal, você precisa estacionar a série tomando seus valores de atraso. UMA processo estacionário permite média, variância e autocorrelação constantes ao longo do tempo. Isso melhora principalmente a previsão de uma série temporal. Isso pode ser feito facilmente com a função diff(). Podemos construir uma série temporal aleatória de dados com uma tendência e então usar a função diff() para estacionar a série. A função diff() aceita um argumento, um vetor, e retorna uma diferença defasada e iterada adequada.

Note: Muitas vezes precisamos criar dados aleatórios, mas para aprendizado e comparação queremos que os números sejam idênticos em todas as máquinas. Para garantir que todos geremos os mesmos dados, usamos a função set.seed() com valores arbitrários de 123. A função set.seed() é gerada através do processo de número pseudoaleatório generator que fazem com que todos os computadores modernos tenham a mesma sequência de números. Se não usarmos a função set.seed(), todos teremos sequências de números diferentes.

set.seed(123)
## Create the data
x = rnorm(1000)
ts <- cumsum(x)
## Stationary the serie
diff_ts <- diff(ts)
par(mfrow=c(1,2))
## Plot the series
plot(ts, type='l')
plot(diff(ts), type='l')

Função Diferença()

função comprimento()

Em muitos casos, queremos saber comprimento de um vetor para cálculo ou para ser usado em um loop for. A função length() conta o número de linhas no vetor x. O seguintewing os códigos importam o conjunto de dados dos carros e retornam o número de linhas.

Note: length() retorna o número de elementos em um vetor. Se a função for passada para uma matriz ou quadro de dados, o número de colunas será retornado.

dt <- cars
## number columns
length(dt)

Saída:

## [1] 1
## number rows
length(dt[,1])

Saída:

## [1] 50

Funções matemáticas

R tem um array de funções matemáticas.

operador Descrição
abs (x) Toma o valor absoluto de x
registro(x,base=y) Toma o logaritmo de x com base y; se a base não for especificada, retorna o logaritmo natural
exp (x) Retorna a exponencial de x
sqrt (x) Retorna a raiz quadrada de x
fatorial (x) Retorna o fatorial de x (x!)
# sequence of number from 44 to 55 both including incremented by 1
x_vector <- seq(45,55, by = 1)
#logarithm
log(x_vector)

Saída:

##  [1] 3.806662 3.828641 3.850148 3.871201 3.891820 3.912023 3.931826
##  [8] 3.951244 3.970292 3.988984 4.007333
#exponential
exp(x_vector)
#squared root
sqrt(x_vector)

Saída:

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

Saída:

##  [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

Funções estatísticas

A instalação padrão do R contém uma ampla gama de funções estatísticas. Neste tutorial, veremos brevemente a função mais importante.

Funções estatísticas básicas

operador Descrição
média(x) Média de x
mediana (x) Mediana de x
var(x) Variância de x
sd(x) Desvio padrão de x
escala (x) Pontuações padrão (pontuações z) de x
quantil (x) Os quartis de x
resumo(x) Resumo de x: média, mínimo, máximo etc.
speed <- dt$speed
speed
# Mean speed of cars dataset
mean(speed)

Saída:

## [1] 15.4
# Median speed of cars dataset
median(speed)

Saída:

## [1] 15
# Variance speed of cars dataset
var(speed)

Saída:

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

Saída:

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

Saída:

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

Saída:

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

Saída:

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

Até este ponto, aprendemos muitas funções integradas do R.

Note: Tenha cuidado com a classe do argumento, ou seja, numérico, booleano ou string. Por exemplo, se precisarmos passar um valor de string, precisamos colocar a string entre aspas: “ABC” .

Função de gravação em R

Em algumas ocasiões, precisamos escrever nossa própria função porque temos que realizar uma tarefa específica e não existe nenhuma função pronta. Uma função definida pelo usuário envolve um nome, argumentos e de um corpo.

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

Note: uma boa prática é nomear uma função definida pelo usuário diferente de uma função integrada. Isso evita confusão.

Função de um argumento

No próximo trecho, definimos uma função quadrada simples. A função aceita um valor e retorna o quadrado do valor.

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

Explicação do código

  • A função é denominada função_quadrada; pode ser chamado como quisermos.
  • Recebe um argumento “n”. Nós não especificou o tipo de variável para que o usuário possa passar um inteiro, um vetor ou uma matriz
  • A função pega a entrada “n” e retorna o quadrado da entrada. Quando terminar de usar a função, podemos removê-la com a função rm().

# depois de criar a função

rm(square_function)
square_function

No console, podemos ver uma mensagem de erro: Erro: objeto 'square_function' não encontrado informando que a função não existe.

Escopo do ambiente

Em R, o meio Ambiente é um coleção de objetos como funções, variáveis, quadro de dados, etc.

R abre um ambiente sempre que o Rstudio é solicitado.

O ambiente de nível superior disponível é o ambiente global, chamado R_GlobalEnv. E nós temos o ambiente local.

Podemos listar o conteúdo do ambiente atual.

ls(environment())

saída

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

Você pode ver todas as variáveis ​​e funções criadas no R_GlobalEnv.

A lista acima irá variar para você com base no código histórico executado no R Studio.

Observe que n, o argumento da função square_function é não neste ambiente global.

A novo ambiente é criado para cada função. No exemplo acima, a função square_function() cria um novo ambiente dentro do ambiente global.

Para esclarecer a diferença entre global e ambiente local, vamos estudar o seguintewing exemplo

Essas funções pegam um valor x como argumento e o adicionam a y definido fora e dentro da função

Escopo do ambiente

A função f retorna a saída 15. Isso ocorre porque y é definido no ambiente global. Qualquer variável definida no ambiente global pode ser usada localmente. A variável y tem o valor 10 durante todas as chamadas de função e está acessível a qualquer momento.

Vamos ver o que acontece se a variável y for definida dentro da função.

Precisamos eliminar `y` antes de executar este código usando rm r

Escopo do ambiente

A saída também é 15 quando chamamos f(5), mas retorna um erro quando tentamos imprimir o valor y. A variável y não está no ambiente global.

Finalmente, R usa a definição de variável mais recente para passar dentro do corpo de uma função. Vamos considerar o seguintewing exemplo:

Escopo do ambiente

R ignora os valores y definidos fora da função porque criamos explicitamente uma variável y dentro do corpo da função.

Função multiargumentos

Podemos escrever uma função com mais de um argumento. Considere a função chamada “tempos”. É uma função simples que multiplica duas variáveis.

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

Saída:

## [1] 8

Quando devemos escrever a função?

O cientista de dados precisa realizar muitas tarefas repetitivas. Na maioria das vezes, copiamos e colamos trechos de código repetidamente. Por exemplo, a normalização de uma variável é altamente recomendada antes de executarmos um aprendizado de máquina algoritmo. A fórmula para normalizar uma variável é:

Fórmula para normalizar uma variável

Já sabemos como usar as funções min() e max() em R. Usamos a biblioteca tibble para criar o quadro de dados. Até agora, Tibble é a função mais conveniente para criar um conjunto de dados do zero.

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

Procederemos em duas etapas para calcular a função descrita acima. Na primeira etapa, criaremos uma variável chamada c1_norm que é o reescalonamento de c1. Na segunda etapa, apenas copiamos e colamos o código c1_norm e alteramos com c2 e c3.

Detalhe da função com a coluna c1:

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

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

Portanto, podemos dividi-los para obter o valor normalizado da coluna c1:

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

Podemos criar c1_norm, c2_norm e c3_norm:

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

Saída:

## [1] 0.3400113 0.4198788 0.8524394 0.4925860 0.5067991

Funciona. Podemos copiar e colar

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

em seguida, altere c1_norm para c2_norm e c1 para c2. Fazemos o mesmo para criar 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))

Redimensionamos perfeitamente as variáveis ​​c1, c2 e c3.

No entanto, este método está sujeito a erros. Poderíamos copiar e esquecer de alterar o nome da coluna após colar. Portanto, uma boa prática é escrever uma função cada vez que precisar colar o mesmo código mais de duas vezes. Podemos reorganizar o código em uma fórmula e chamá-lo sempre que necessário. Para escrever nossa própria função, precisamos fornecer:

  • Nome: normalizar.
  • o número de argumentos: precisamos apenas de um argumento, que é a coluna que usamos em nosso cálculo.
  • O corpo: esta é simplesmente a fórmula que queremos retornar.

Procederemos passo a passo para criar a função normalizar.

Passo 1) Nós criamos o nominador, qual é . Em R, podemos armazenar o nomeador em uma variável como esta:

nominator <- x-min(x)

Passo 2) nós calculamos o denominador: . Podemos replicar a ideia do passo 1 e armazenar o cálculo em uma variável:

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

Passo 3) Realizamos a divisão entre o denominador e o denominador.

normalize <- nominator/denominator

Passo 4) Para retornar valor para a função de chamada, precisamos passar normalize dentro de return() para obter a saída da função.

return(normalize)

Passo 5) Estamos prontos para usar a função envolvendo tudo dentro do colchete.

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

Vamos testar nossa função com a variável c1:

normalize(data_frame$c1)

Funciona perfeitamente. Criamos nossa primeira função.

As funções são uma forma mais abrangente de realizar uma tarefa repetitiva. Podemos usar a fórmula de normalização em diferentes colunas, como abaixo:

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)

Embora o exemplo seja simples, podemos inferir o poder de uma fórmula. O código acima é mais fácil de ler e principalmente evita erros ao colar códigos.

Funções com condição

Às vezes, precisamos incluir condições em uma função para permitir que o código retorne resultados diferentes.

Nas tarefas de aprendizado de máquina, precisamos dividir o conjunto de dados entre um conjunto de treinamento e um conjunto de teste. O conjunto de trens permite que o algoritmo aprenda com os dados. Para testar o desempenho do nosso modelo, podemos usar o conjunto de testes para retornar a medida de desempenho. R não possui uma função para criar dois conjuntos de dados. Podemos escrever nossa própria função para fazer isso. Nossa função recebe dois argumentos e é chamada split_data(). A ideia por trás é simples: multiplicamos o comprimento do conjunto de dados (ou seja, número de observações) por 0.8. Por exemplo, se quisermos dividir o conjunto de dados 80/20, e nosso conjunto de dados contiver 100 linhas, então nossa função irá multiplicar 0.8*100 = 80. 80 linhas serão selecionadas para se tornarem nossos dados de treinamento.

Usaremos o conjunto de dados de qualidade do ar para testar nossa função definida pelo usuário. O conjunto de dados de qualidade do ar possui 153 linhas. Podemos ver isso com o código abaixo:

nrow(airquality)

Saída:

## [1] 153

Procederemos da seguinte forma:

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

Nossa função tem dois argumentos. O trem de argumentos é um parâmetro booleano. Se estiver definido como TRUE, nossa função cria o conjunto de dados do trem, outroswise, ele cria o conjunto de dados de teste.

Podemos proceder como fizemos com a função normalise(). Escrevemos o código como se fosse apenas um código único e, em seguida, agrupamos tudo com a condição no corpo para criar a função.

-

Precisamos calcular o comprimento do conjunto de dados. Isso é feito com a função nrow(). Nrow retorna o número total de linhas no conjunto de dados. Chamamos o comprimento variável.

length<- nrow(airquality)
length

Saída:

## [1] 153

-

Multiplicamos o comprimento por 0.8. Ele retornará o número de linhas a serem selecionadas. Deve ser 153 * 0.8 = 122.4

total_row <- length*0.8
total_row

Saída:

## [1] 122.4

Queremos selecionar 122 linhas entre as 153 linhas do conjunto de dados de qualidade do ar. Criamos uma lista contendo valores de 1 a total_row. Armazenamos o resultado na variável chamada split

split <- 1:total_row
split[1:5]

Saída:

## [1] 1 2 3 4 5

split escolhe as primeiras 122 linhas do conjunto de dados. Por exemplo, podemos ver que nossa variável split reúne os valores 1, 2, 3, 4, 5 e assim por diante. Esses valores serão o índice quando selecionarmos as linhas a serem retornadas.

-

Precisamos selecionar as linhas no conjunto de dados de qualidade do ar com base nos valores armazenados na variável de divisão. Isso é feito assim:

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

Saída:

##[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

-

Podemos criar o conjunto de dados de teste usando as linhas restantes, 123:153. Isso é feito usando – na frente de split.

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

Saída:

##[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

-

Podemos criar a condição dentro do corpo da função. Lembre-se, temos um trem de argumentos que é um booleano definido como TRUE por padrão para retornar o conjunto de trens. Para criar a condição, usamos a sintaxe if:

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

É isso, podemos escrever a função. Precisamos apenas alterar a qualidade do ar para df porque queremos testar nossa função para qualquer quadro de dados, não apenas qualidade do ar:

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

Vamos tentar nossa função no conjunto de dados de qualidade do ar. deveríamos ter um conjunto de trem com 122 linhas e um conjunto de teste com 31 linhas.

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

Saída:

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

Saída:

## [1] 31  6