<- function(arguments) {
name
bodyreturn(objeto que guarda o resultado final)
}
Funções
Definição
Funções são blocos de código que podem ser chamados para realizar uma tarefa específica
Elas facilitam a organização do código, promovem a reutilização e tornam o código mais organizados.
As funções permitem-lhe reduzir a duplicação de código, automatizando uma tarefa generalizada a ser aplicada recursivamente.
Dica: você deve considerar escrever uma função sempre que copiar e colar um bloco de código mais de duas vezes
Para definir uma função em R, você usa a palavra-chave
function
seguida pelos parâmetros/argumentos da função e o corpo da função
Funções são objetos, assim como vetores são objetos.
De forma geral, as funções podem ser divididas em três partes:
O
formals()
, a lista de argumentos que controlam como você chama a função.O
body()
, o código dentro da função.O
environment()
, a estrutura de dados que determina como a função encontra os valores associados aos nomes.
Embora os
formals()
e obody()
sejam especificados explicitamente quando você cria uma função, oenvironment()
é especificado implicitamente, com base em onde você definiu a função.O
environment()
da função sempre existe, mas só é impresso quando a função não está definida no ambiente global.f(x) = 2x
= function(x){
f_x = 2*x # função
f_x return(f_x)
}
= c(1,2,3,4)
x y = f_x(x)) (
[1] 2 4 6 8
args(f_x)
function (x)
NULL
plot(x,y)
formals(f_x)
$x
body(f_x)
{
f_x = 2 * x
return(f_x)
}
environment(f_x)
<environment: R_GlobalEnv>
attr(f_x, "srcref")
function(x){
f_x = 2*x # função
return(f_x)
}
- Média de um vetor numérico
= function(x){
media = sum(x)/length(x)
media_x return(media_x)
}= sample(1:100,20,replace=T)
y media(y)
[1] 51.25
mean(y)
[1] 51.25
- Função para fazer uma correspondência entre o número e o dia da semana
<- function(numero_dia) {
dia_semana <- switch(
dia
numero_dia,"1" = "Domingo",
"2" = "Segunda-feira",
"3" = "Terça-feira",
"4" = "Quarta-feira",
"5" = "Quinta-feira",
"6" = "Sexta-feira",
"7" = "Sábado"
)return(cat("O dia correspondente ao número", numero_dia, "é", dia, "\n"))
}dia_semana(2)
O dia correspondente ao número 2 é Segunda-feira
Argumentos Faltantes
A função
missing
em R é usada para verificar se um argumento foi fornecido a uma função.Isso é particularmente útil quando você deseja definir um comportamento padrão ou tomar decisões com base na presença ou ausência de argumentos.
# Função para somar dois números com valores padrão
<- function(a, b) {
soma_com_default if (missing(a)) {
<- 0
a
}
if (missing(b)) {
<- 0
b
}
return(a + b)
}
# Testando a função com diferentes combinações de argumentos
print(soma_com_default(3, 5)) # Ambos os argumentos fornecidos: 8
[1] 8
print(soma_com_default(3)) # Apenas 'a' fornecido: 3
[1] 3
print(soma_com_default(b = 5)) # Apenas 'b' fornecido: 5
[1] 5
print(soma_com_default()) # Nenhum argumento fornecido: 0
[1] 0
- Observe como o argumento
size
é definido na funçãosample
sample
function (x, size, replace = FALSE, prob = NULL)
{
if (length(x) == 1L && is.numeric(x) && is.finite(x) && x >=
1) {
if (missing(size))
size <- x
sample.int(x, size, replace, prob)
}
else {
if (missing(size))
size <- length(x)
x[sample.int(length(x), size, replace, prob)]
}
}
<bytecode: 0x00000294a067def0>
<environment: namespace:base>
Argumentos padrão
- A função pode ser construída com argumentos pré-definidos
= function(x = c(1,2,3,4)){
media return( sum(x)/length(x))
}media()
[1] 2.5
Funções primitivas
- Há uma exceção à regra de que uma função possui três componentes. Funções primitivas, como
sum()
e[
, chamam o código C diretamente.
sum
function (..., na.rm = FALSE) .Primitive("sum")
`[`
.Primitive("[")
- Essas funções existem principalmente em C, não em R, então seus
formals()
,body()
eenvironment()
são todosNULL
:
…
dot,dot,dot
- Na definição de uma função, você pode usar três pontos (
...
) para indicar que a função aceita argumentos adicionais. - Esses argumentos adicionais não precisam ser explicitamente listados na definição da função
- Esses argumentos adicionais geralmente são passados para outras funções dentro do corpo da função.
- No exemplo abaixo,
...
permite a passagem de argumentos adicionais, comona.rm
para remover valores ausentes ao calcular a média.
<- function(valores,pesos,...) {
media_ponderada # Calcula a média ponderada
<- sum(valores * pesos,...) / sum(pesos,...)
resultado return(resultado)
}media_ponderada(c(1,2,NA),c(1,2,3))
[1] NA
media_ponderada(c(1,2,NA),c(1,2,3),na.rm=T)
[1] 0.8333333
on.exit
A função
on.exit
é usada para especificar código que deve ser executado quando a execução de uma função é concluídaFrequentemente usada para garantir que determinadas ações sejam realizadas antes que a função termine, independentemente de como ele termina
No exemplo a seguir vamos trocar de diretório
<- "colocar caminho" # diretório atual
names_wd_atual <- setwd(names_wd_atual)
wd_atual
<- function() {
criar_grafico x11() # abrindo nova janela para a figura
<- paste0(wd_atual,"/Figuras/figura_exemplo_on_exit.jpg")
new_wd jpeg(new_wd) # salvando figura no novo diretório
plot(1:10, main = "Meu Gráfico", ylab = "Valores")
# Configura on.exit para fechar o dispositivo gráfico ao sair
on.exit({
dev.off()
cat("Fechando o dispositivo gráfico\n")
setwd(wd_atual) # voltando para o diretório atual
cat("voltando para o diretório atual\n")
add = TRUE)
},
}
# Chama a função
criar_grafico()
Formas de Funções
Embora tudo o que acontece em R seja resultado de uma função, nem todos as funções são formuladas da mesma forma.
Existem quatro formas de funções:
Prefix Functions
Infix Functions
Replacement Functions
Special functios
Prefix Functions
- São as funções padrão ou regulares, identificadas por um nome seguido de argumentos entre parênteses.
<- function(x,peso=c(1,1,1),...)return(sum(peso*x,...)/sum(peso,...))
media_ponderada
media_ponderada(c(1,2,3)) # o nome da função vem antes de seus argumento
[1] 2
Infix Functions
O nome da função fica entre seus argumentos
As formas infixas são usadas para muitos operadores matemáticos e para funções definidas pelo usuário que começam e terminam com
%
[1] -1
[1] 5
[1] 6
[1] 0.6666667
<- c(1,2,3,4,5)
x 6 %in% x # o número 6 pertence ao conjuto x?
[1] FALSE
<- c(1,2,3,4,5)
x 2 %in% x # o número 2 pertence ao conjuto x?
[1] TRUE
= matrix(c(1,2,3,4),2,2)
mat1 = matrix(c(1,2,3,4),2,2)
mat2 %*% mat2 # multiplicação de matriz mat1
[,1] [,2]
[1,] 7 15
[2,] 10 22
- Definindo nova função infix
`%+%` <- function(a, b) paste(a, b,sep="-")
"new " %+% "string"
[1] "new -string"
- A biblioteca
magrittr
adiciona o operador pipe, que permite usar a saída de uma função como entrada de outra função
require(magrittr) # pacote para usar %>%
<- c(1,2,3,4)
x = sqrt( var(x) )
desvio_padrao = var(x) %>% sqrt()
desvio_padrao = var(x) |> sqrt() # pacote base desvio_padrao
- Os colchetes transformam o pipe no que é quase uma função anônima
1:5 %>% {(. + 1) / 2} # 1:5 são utilizados no lugar do ponto
[1] 1.0 1.5 2.0 2.5 3.0
Replacement Functions
- Estas funções são frequentemente usadas para atribuir valores a variáveis ou modificar objetos existentes.
'function_name<-' <- function(x, additional arguments, value)
{ function body
}
- Nomear elementos do vetor com a função
names
= c(1,2,3,4)
x names(x) <- paste0("n",1:length(x))
x
n1 n2 n3 n4
1 2 3 4
- Mudar o segundo elemento do vetor
"replace_second<-" = function(x,value){
2] <- value
x[
x
}= c(1,2,3,4)
x replace_second(x) <- 0L
x
[1] 1 0 3 4
'modify<-' <- function(x, position, value) {
<- value
x[position]
x
}= 1:5
x modify(x, 1) <- 2 # value=2
x
[1] 2 2 3 4 5
Special Functions
Funções especiais muitas vezes desempenham papéis específicos, como manipulação condicional, filtragem de dados e manipulação de strings.
Ferramentas de controle de fluxo
if (cond) true
(`if`(cond, true)
)if (cond) true else false
(`if`(cond, true, false)
)for(var in seq) action
(`for`(var, seq, action)
)while(cond) action
(`while`(cond, action)
)repeat expr
(`repeat`(expr)
)next
(`next`()
)break
(`break`()
)
Condições
O sistema de condições fornece um conjunto de ferramentas que permitem ao autor de uma função indicar que algo incomum está acontecendo
O autor da função sinaliza condições com funções como
stop()
(para erros),warning()
( para avisos) emessage()
(para mensagens)Compreender o sistema de condições é importante porque muitas vezes você precisará desempenhar as duas funções: sinalizar as condições das funções que você cria e lidar com as condições sinalizadas pelas funções que você chama.
Erro (Stop Condition):
- A função
stop()
é usada para sinalizar um erro. Quando um erro é sinalizado, a execução do código é interrompida e uma mensagem de erro é exibida.
<- function(x) {
calcular_media if (length(x) == 0) {
stop("Erro: O vetor está vazio.")
}if (is.numeric(x) == F) {
stop("Erro: vetor deve ser do tipo numérico")
}return(mean(x))
}calcular_media(1:4)
[1] 2.5
<- function(x) {
calcular_media if (length(x) == 0) {
stop("Erro: O vetor está vazio.")
}if (is.numeric(x) == F) {
stop("Erro: vetor deve ser do tipo numérico")
}return(mean(x))
}calcular_media(c(1,2,3,"l"))
# Error in calcular_media(c(1, 2, 3, "l")) :
# Erro: vetor deve ser do tipo numérico
Aviso (Warning Condition):
- A função
warning()
é usada para sinalizar um aviso. Um aviso não interrompe a execução do código, mas alerta o usuário sobre algo que pode ser problemático.
<- function(x) {
calcular_raiz_quadrada if (any(x < 0)) {
warning("Alguns valores são negativos. A raiz quadrada de números negativos será tratada como NaN.")
}return(sqrt(x))
}
# Exemplo de uso
<- calcular_raiz_quadrada(c(4, -9, 16))
resultado print(resultado)
[1] 2 NaN 4
Mensagem Informativa (Message Condition):
- A função
message()
é usada para sinalizar mensagens informativas. Essas mensagens são úteis para fornecer informações adicionais durante a execução do código.
<- function(x) {
calcular_cubo message("Calculando o cubo dos valores.")
return(x^3)
}
# Exemplo de uso
<- calcular_cubo(c(2, 3, 4))
resultado print(resultado)
[1] 8 27 64
Ignorando as condições
- Ao lidar com condições em R, você pode usar as funções
try()
,suppressWarnings()
, esuppressMessages()
para controlar o tratamento de erros, avisos e mensagens.
try()
- A função
try()
é usada para avaliar expressões e manipular erros sem interromper a execução do código. Ela retorna um objeto que você pode verificar usandoinherits()
para determinar se ocorreu um erro.
= c()
x mean(x)
[1] NA
<- try(mean(), silent = TRUE)
resultado resultado
[1] "Error in mean.default() : argumento \"x\" ausente, sem padrão\n"
attr(,"class")
[1] "try-error"
attr(,"condition")
<simpleError in mean.default(): argumento "x" ausente, sem padrão>
if (inherits(resultado, "try-error")) { # verifica se o objeto resultado é da classe "try-error
cat("Erro: Ocorreu um problema ao calcular a média.\n")}
Erro: Ocorreu um problema ao calcular a média.
suppressWarnings()
para Suprimir Avisos:
- A função
suppressWarnings()
é usada para executar uma expressão e suprimir os avisos que ela pode gerar.
= c()
x mean(x)
Warning in mean.default(x): argumento não é numérico nem lógico: retornando NA
[1] NA
suppressWarnings(mean(x))
[1] NA
suppressMessages()
para Suprimir Mensagens:
- A função
suppressMessages()
é usada para executar uma expressão e suprimir as mensagens informativas que ela pode gerar.
<- function(x) {
calcular_cubo message("Calculando o cubo dos valores.")
return(x^3)
}
# Exemplo de uso
<- suppressMessages(calcular_cubo(c(2, 3, 4)))
resultado resultado
[1] 8 27 64
Invocando funções
Normalmente você chama uma função colocando seus argumentos, entre parênteses, após seu nome:
mean(1:10, na.rm = TRUE)
Porém, em algumas situações você tem uma lista de argumentos que deseja passar para uma função.
A função
do.call
em R é usada para chamar uma função e passar argumentos para ela na forma de uma lista
Exemplo 1
# Lista de argumentos
<- list(1, 2, 3, 4, 5)
args
# Usando do.call para chamar a função sum
<- do.call(sum, args)
resultado print(resultado) # Isso imprimirá 15
[1] 15
Exemplo 2
- Você pode usar
do.call
com funções que têm parâmetros nomeados
# Definindo uma função que cria uma sequência
<- function(inicio, fim, passo = 1) {
criar_sequencia return(seq(from = inicio, to = fim, by = passo))
}
# Lista de argumentos com parâmetros nomeados
<- list(inicio = 1, fim = 10, passo = 2)
args
# Usando do.call para chamar a função criar_sequencia
<- do.call(criar_sequencia, args)
sequencia print(sequencia)
[1] 1 3 5 7 9
Exemplo 3
- Um uso comum de
do.call
é combinar listas de data frames:
# Criando dois data frames
<- data.frame(a = 1:3, b = 4:6)
df1 <- data.frame(a = 7:9, b = 10:12)
df2
# Lista de data frames
<- list(df1, df2)
dfs
# Usando do.call com rbind para combinar os data frames
<- do.call(rbind, dfs)
df_combinado print(df_combinado)
a b
1 1 4
2 2 5
3 3 6
4 7 10
5 8 11
6 9 12
# Criando dois data frames
<- data.frame(a = 1:3, b = 4:6)
df1 <- data.frame(c = 7:9, d = 10:12)
df2
# Lista de data frames
<- list(df1, df2)
dfs
# Usando do.call com rbind para combinar os data frames
<- do.call(cbind, dfs)
df_combinado print(df_combinado)
a b c d
1 1 4 7 10
2 2 5 8 11
3 3 6 9 12
Exemplo 4
- Selecionar funções baseada em condições
<- list(c(1, 2, 3), c(4, 5, 6))
vectors = "SOMA"
op
if (op == "SOMA") {
<- do.call("+", vectors)
result else if(op != "SOMA")
}
{<- do.call("*", vectors)
result
}
result
[1] 5 7 9
Exemplo 5
- Usando a função
paste
<- list("Hello", "world!", "How", "are", "you?")
strings_list strings_list
[[1]]
[1] "Hello"
[[2]]
[1] "world!"
[[3]]
[1] "How"
[[4]]
[1] "are"
[[5]]
[1] "you?"
# Combine strings in the list into a single sentence
do.call(paste, c(strings_list,sep=" "))
[1] "Hello world! How are you?"
Função Anônima
Embora quase sempre você crie uma função e depois a vincule a um nome, a etapa de vinculação não é obrigatória.
Se você optar por não dar um nome a uma função, obterá uma função anônima .
= list(c(rnorm(100)))
y
do.call(what = function(x) var(x)|> sqrt(),args = y)
[1] 0.9239861
# Criando um vetor de números
<- c(1, 5, 8, 3, 7, 2)
numeros
# Usando Filter com uma função anônima
<- Filter(function(x) x^2 > 4, numeros)
filtrados
print(filtrados)
[1] 5 8 3 7
integrate(function(x) exp(-x), 0, Inf)
1 with absolute error < 5.7e-05
integrate(function(x) dnorm(x), -3, 3)
0.9973002 with absolute error < 9.3e-07
Vantagens das Funções Anônimas:
Conveniente para Operações Simples: Funções anônimas são úteis para operações simples que não precisam ser reutilizadas em outros lugares do código.
Reduz Poluição do Espaço de Nomes: Como não possuem um nome explícito, elas não poluem o espaço de nomes com funções que são usadas apenas uma vez.
Lista de funções
- Funções em uma lista
<- list(
funs half = function(x) x / 2,
mult = function(x) x * 2
)$mult(10) funs
[1] 20
Atividade
Escreva uma função que, dado um número de 1 a 12, imprima o nome do mês do ano correspondente.
O coeficiente de variação (cv) é uma forma de medir a variabilidade dos dados. Crie uma função que calcule o coeficiente de variação de um vetor numérico. Crie uma condição para que se o vetor não for do tipo numeric, não faça o cálculo
Crie uma função para criar um objeto de uma classe chamada “Livro” que representa um livro com atributos como autor e ano de publicação.
Considere a seguinte função: f(x) = (x - 3)^2 + 5 se 0=<x<10 e f(x) = 54 se x>=10. Escreva uma função considerando: erro para entrada do tipo não numérico e erro para entrada de valores negativos.
Considere os argumentos x e y. Use o conceito de função infix para saber se x é divisível por Y.
Crie um exemplo usando a função try. Se for erro, atribua NaN ao objeto da class try-error e imprima mensagem de erro