Tutorial guiado 1 · Criando funções em R
Criar funções em R é um dos passos mais importantes para
automatizar tarefas, evitar repetição de código e estruturar análises de
dados de forma profissional.
Neste tutorial você vai realizar cinco exercícios práticos e graduais baseados no ecossistema e nos conceitos que foram apresentados no decorrer do módulo.
Todos os exercícios tem uma solução sugerida e comentada. Mas recomendo que só olhe a solução após tentar resolver sozinho.
1. Conversor de Temperatura com Validação Lógica
Escreva uma função chamada celsius_para_fahrenheit que receba uma temperatura em graus Celsius e a converta para Fahrenheit. A fórmula matemática é:
\[F = C \times 1.8 + 32\]
Se o usuário passar um valor que não seja numérico, a função deve interromper a execução e exibir uma mensagem amigável de erro usando a função stop().
celsius_para_fahrenheit <- function(celsius) {
# Validação de tipo: garante que a entrada seja numérica
if (!is.numeric(celsius)) {
stop("Erro: A entrada fornecida deve ser um valor numérico!")
}
# Aplicação da fórmula matemática
fahrenheit <- (celsius * 1.8) + 32
# Retorno explícito do resultado
return(fahrenheit)
}
# --- Testes da Função ---
celsius_para_fahrenheit(25) # Retorna: 77
celsius_para_fahrenheit(0) # Retorna: 32
# celsius_para_fahrenheit("vinte") # Descomente para ver o erro controlado pelo stop()
2. Cálculo do Índice de Massa Corporal (IMC) com Classificação
Crie uma função chamada calcular_imc que receba o peso (em kg) e a altura (em metros) de uma pessoa. A função deve calcular o IMC através da fórmula:
\[IMC = \frac{peso}{altura^2}\]
Em seguida, ela deve retornar uma string classificando o indivíduo de acordo com as regras:
- Se IMC < 18.5: “Abaixo do peso”;
- Se IMC >= 18.5 e IMC < 25: “Peso normal”;
- Se IMC >= 25: “Sobrepeso”.
calcular_imc <- function(peso, altura) {
# Cálculo do IMC utilizando potenciação
imc <- peso / (altura^2)
# Estrutura de controle condicional IF-ELSE para classificação
if (imc < 18.5) {
classificacao <- "Abaixo do peso"
} else if (imc >= 18.5 & imc < 25) {
classificacao <- "Peso normal"
} else {
classificacao <- "Sobrepeso"
}
# Criamos uma mensagem clara combinando os resultados
resultado_texto <- paste0("IMC: ", round(imc, 2), " -> Classificação: ", classificacao)
return(resultado_texto)
}
# --- Testes da Função ---
calcular_imc(peso = 70, altura = 1.75) # Retorna: "IMC: 22.86 -> Classificação: Peso normal"
calcular_imc(peso = 90, altura = 1.80) # Retorna: "IMC: 27.78 -> Classificação: Sobrepeso"
Estatísticas Resumo de Vetores Tratando NA
Desenvolva uma função chamada analisar_vetor que receba um vetor numérico. Ela deve calcular e retornar uma lista nomeada contendo três estatísticas: a Média, o Desvio Padrão e o Coeficiente de Variação (\(CV = \frac{Desvio\ Padrão}{Média}\)).
A função deve conter um argumento lógico chamado
remover_na cujo valor padrão é TRUE.
Se este argumento estiver ativo, a função deve ignorar os valores
NA nos cálculos
analisar_vetor <- function(vetor, remover_na = TRUE) {
# Tratamento inicial: Se o usuário passar apenas NAs e remover_na for TRUE
if (all(is.na(vetor))) {
return(list(media = NA, desvio_padrao = NA, cv = NA))
}
# Cálculo das estatísticas repassando o parâmetro de remoção de NA
v_media <- mean(vetor, na.rm = remover_na)
v_sd <- sd(vetor, na.rm = remover_na)
v_cv <- v_sd / v_media
# Armazenamos os resultados em uma lista estruturada e nomeada
resultado <- list(
media = round(v_media, 2),
desvio_padrao = round(v_sd, 2),
cv = round(v_cv, 3)
)
return(resultado)
}
# --- Testes da Função ---
notas_turma <- c(7.5, 8.0, NA, 6.0, 9.5)
# Teste com remoção automática de NA (padrão)
analisar_vetor(notas_turma)
# Retorna: $media [1] 7.75, $desvio_padrao [1] 1.44, $cv [1] 0.186
# Teste forçando a manutenção de NA
analisar_vetor(notas_turma, remover_na = FALSE)
# Retorna tudo como NA, pois o R propaga o NA nas funções matemáticas básicas
Substituição Vetorizada Condicional
Ao lidar com tabelas e vetores, o if comum falha se passarmos
múltiplos valores de uma vez. Crie uma função chamada
limpar_limites que receba um vetor numérico, um
limite_inferior e um limite_superior. A função deve inspecionar o vetor
e substituir qualquer valor menor que o limite inferior pela string
“Abaixo” e qualquer valor maior que o limite superior pela string
“Acima”. Os valores que estiverem dentro do intervalo devem ser mantidos
como texto. Utilize a função vetorizada ifelse() para
construir a solução.
limpar_limites <- function(vetor, limite_inferior, limite_superior) {
# O uso de ifelse aninhado permite avaliar todo o vetor simultaneamente (vetorização)
resultado_vetorial <- ifelse(vetor < limite_inferior, "Abaixo",
ifelse(vetor > limite_superior, "Acima",
as.character(vetor)))
return(resultado_vetorial)
}
# --- Testes da Função ---
dados_sensores <- c(12, 45, 98, 5, 50, 105, 30)
# Aplicando limites de 10 a 90
limpar_limites(dados_sensores, limite_inferior = 10, limite_superior = 90)
# Retorna: "12" "45" "Acima" "Abaixo" "50" "Acima" "30"
5. Função de Manipulação Avançada de Data Frames
Escreva uma função chamada sumarizar_categoria_base que
receba três argumentos: um data frame (dados), o nome da coluna de
agrupamento como string (coluna_grupo) e o nome da coluna numérica de
valores como string (coluna_valores).
A função deve calcular a média da coluna de valores para cada grupo e contar quantos registros existem em cada categoria. O retorno deve ser um único data.frame contendo as colunas: a categoria, a contagem e a média (ordenada da maior média para a menor).
sumarizar_categoria_base <- function(dados, coluna_grupo, coluna_valores) {
# 1. Validação de segurança: garante que o objeto principal é um data.frame
if (!is.data.frame(dados)) {
stop("O argumento 'dados' precisa ser um data.frame válido!")
}
# 2. Extração dos vetores usando a indexação de strings padrão do R base
vetor_grupo <- dados[[coluna_grupo]]
vetor_valores <- dados[[coluna_valores]]
# 3. Cálculo das Médias por Grupo
# A função aggregate() divide o vetor de valores de acordo com o grupo e aplica a função
df_medias <- aggregate(vetor_valores ~ vetor_grupo, data = dados, FUN = mean, na.rm = TRUE)
colnames(df_medias) <- c(coluna_grupo, "Media") # Renomeando as colunas geradas
# 4. Cálculo da Contagem de Linhas por Grupo
# Usamos a função table() para contar a frequência das categorias e convertemos em data.frame
df_contagem <- as.data.frame(table(vetor_grupo))
colnames(df_contagem) <- c(coluna_grupo, "Contagem")
# 5. Combinação dos resultados (Junção)
# No R base, a função merge() funciona como um join relacional automático entre tabelas
tabela_resumo <- merge(df_contagem, df_medias, by = coluna_grupo)
# 6. Ordenação Decrescente pela Média
# Usamos a função order() com o sinal de menos (-) para ordernar do maior para o menor
linhas_ordenadas <- order(tabela_resumo$Media, decreasing = TRUE)
tabela_final <- tabela_resumo[linhas_ordenadas, ]
# Removemos os nomes automáticos de linhas para deixar a tabela limpa
rownames(tabela_final) <- NULL
return(tabela_final)
}
# --- Teste da Função com R Básico ---
# Vamos testar usando o conjunto de dados nativo do R chamado 'iris'
# Ele contém as colunas textuais/fatores "Species" e numéricas como "Sepal.Length"
resultado_base <- sumarizar_categoria_base(
dados = iris,
coluna_grupo = "Species",
coluna_valores = "Sepal.Length"
)
# Imprimindo o resultado no console
print(resultado_base)
# Saída Esperada no Console:
# Species Contagem Media
# 1 virginica 50 6.588000
# 2 versicolor 50 5.936000
# 3 setosa 50 5.006000
Dicas para construção de funções
Acessando Colunas Dinamicamente: Quando o nome da coluna está guardado em uma variável de texto (ex: coluna_grupo <- “Species”), você não pode usar o cifrão (dados$coluna_grupo), pois o
Rprocurará uma coluna literalmente chamada “coluna_grupo”. A forma correta noRbase é usar os colchetes duplos: dados[[coluna_grupo]].Função aggregate(): Essa função é o canivete suíço do
Rbase para estatísticas descritivas. A sintaxe de fórmulavetor_valores ~ vetor_grupolê-se nativamente como: “calcule a função (FUN) da variável à esquerda em função das categorias da variável à direita”.