6.4 Criando ou modificando funções
Funções são objetos que contêm um script que usa os argumentos (também objetos) para executar alguma coisa.
A expressão function(){}
é utilizada para criar funções.
Criar funções é útil pois podem executar algo várias vezes (podendo ser de forma diferente) sem precisar reescrever o código todas às vezes.
Isso nos auxilia em práticas rotineiras como, por exemplo, na manipulação de um conjunto de dados de localização geográfica de espécimes botânicos.
Podemos gerar um mapa personalizado de distribuição geográfica de cada espécie criando uma função para plotar um mapa, e depois utilizamos a aplicamos a função sobre a categoria, neste caso, a variável contendo o nome da espécie.
É muito útil também poder modificar uma função criada por outra pessoa, seja uma função de um determinado pacote ou uma função que você encontrou em uma página qualquer navegando pela internet.
É muito simples construir uma função. Há um bloco que deve ser sempre repetido:
function(meu_argumento1, meu_argumento2, ...) {
# AQUI FICAM AS AÇÕES DE SUA FUNÇÃO, COMO POR EXEMPLO
return("resultado da função") #
}
É costume sempre utilizar a função return()
como último elemento da função para que algum objeto seja retornado ao usuário.
# veja o help ?return
6.4.1 Exemplo I
Vamos fazer a nossa versão da função mean()
, que tira a média aritmética dos valores de um vetor.
# Vamos fazer essa função na unha:
<- function(x) {
amedia # x será um vetor de comprimento >=1 e todos os valores devem ser numéricos, senão precisamos avisar.
# essa funçao ira retornar o valor do 'am' que definimos como nulo inicialmente
<- NULL
am # condicao 1
<- is.vector(x)
c1 # condicao 2
<- as.numeric(x) # convertemos em numérico
xx <- xx[!is.na(xx)] # tira o que não é número (o que não foi convertido ou está em branco)
xx <- length(xx) == length(x) # os comprimentos são iguais? e tem algum valor?
c2 if (c1 & length(xx) > 0) { # se for um vetor e houver algum valor numérico, pode calcular a média
<- sum(xx) / length(xx)
am if (!c2) { # se c1 for falso
print(paste(length(x) - length(xx), " valores do vetor não são numéricos e foram excluídos")) # avisa
}else {
} print("O objeto não é um vetor ou não há valores numéricos") # avisa
}return(am)
}
Vamos agora utilizar a função:
<- c(1, 2, 3, 4, 5, 6)
v1 amedia(v1)
## [1] 3.5
<- c(3, 3, 3, 3, 3, 3, 3)
v1 amedia(v1)
## [1] 3
<- c(3, 3, 3, 3, 3, 3, "A")
v1 amedia(v1)
## Warning in amedia(v1): NAs introduced by coercion
## [1] "1 valores do vetor não são numéricos e foram excluídos"
## [1] 3
<- LETTERS
v1 amedia(v1)
## Warning in amedia(v1): NAs introduced by coercion
## [1] "O objeto não é um vetor ou não há valores numéricos"
## NULL
6.4.2 Exemplo II
Os loops por meio da expressão for(){}
e a condicional if
são muito úteis dentro de funções.
Sua função pode, por exemplo, ser construida para que um argumento possa assumir diferentes valores e, a depender do valor, executar uma coisa diferente.
Como exemplo, vamos criar uma função que contem o script do exemplo de if
:
# CRIA uma funcao com os seguintes argumentos:
# vet = um vetor de valores
# busca.valor = um valor para busca em vet
# nrun = numero de vezes da iteracao
<- function(vet, busca.valor, nrun) {
minhafuncao # cria um loop do número de vezes (note o argumento nrun abaixo)
for (v in 1:nrun) {
# pega um valor aleatorio
# amostra o indice aleatoriamente
<- sample(1:length(vet), 1)
idx <- vet[idx]
valor # se o valor amostrado for igual ao valor procurado para
if (valor == busca.valor) {
# se o valor selecionado aleatoriamente for 10, ou seja se a expressão valor==10 for TRUE execute:
# imprima isso
# print(paste("A primeira vez que o valor 10 foi selecionado aleatoriamente foi quando o objeto v assumiu o valor de",v))
# interrompa (quebre) o loop
break # note este argumento
else {
} # caso contrario, valor!=10, imprime o valor selecionado e continua o loop
# print(paste("O valor selecionado foi ",valor,"no indice",v))
}
}# o valor do objeto v será o último valor assumido na execucao do for(){}, se tiver encontrado será menor que nrun, caso contrario será ==nrun
# se encontrou retorna o indice do valor (que é o último valor assumido por idx)
# caso o último valor seja == ao valor buscado, ou que o ultimo v é menor que o especificado em nrun, retorna o indice do valor no vetor vet
if (v < nrun | valor == busca.valor) {
print(paste("Encontrei o valor", busca.valor, "no indice, ", idx, "do vetor indicado"))
return(idx)
else {
} # caso contrário returna NA
print(paste("Não encontrei o valor", busca.valor, "no vetor indicado"))
return(NA)
} }
Vamos utilizar a função recém-criada:
<- sample(10:100, 60, replace = T)
umvetor minhafuncao(vet = umvetor, busca.valor = 22, nrun = 1000)
## [1] "Não encontrei o valor 22 no vetor indicado"
## [1] NA
<- minhafuncao(vet = umvetor, busca.valor = 22, nrun = 1000) retornou.isso
## [1] "Não encontrei o valor 22 no vetor indicado"
# e usar de novo com outros valores
<- sample(200:300, 50, replace = T)
umvetor sort(table(umvetor), decreasing = T)[1:10]
255 | 210 | 219 | 228 | 260 | 261 | 264 | 269 | 201 | 202 |
---|---|---|---|---|---|---|---|---|---|
3 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 1 | 1 |
minhafuncao(vet = umvetor, busca.valor = 250, nrun = 10000)
## [1] "Encontrei o valor 250 no indice, 36 do vetor indicado"
## [1] 36
<- minhafuncao(vet = umvetor, busca.valor = 250, nrun = 10000) retornou.isso
## [1] "Encontrei o valor 250 no indice, 36 do vetor indicado"