R: Funções do R

Última atualização: 2026-08-26

Nas últimas 6 aulas, temos usado as funções embutidas do R (sum() mean() c()). Mas o que realmente torna o R poderoso é a possibilidade de escrever suas próprias funções. Nesta aula, aprenderemos sobre as “funções personalizadas” do R — transformando código repetitivo em ferramentas reutilizáveis.

O R é uma linguagem de programação funcional, na qual as funções são “cidadãos de primeira classe”. Isso significa que as funções podem ser atribuídas a variáveis, passadas como argumentos e retornadas como valores. Nesta aula, exploraremos todos os recursos das funções do R.

1. O que você vai aprender



2. Uma história sobre a reutilização de código

(1) Problema: Código duplicado

Chen é um analista de dados que precisa “converter dados de vendas em relatórios” 10 vezes por dia. A cada vez, ele escreve a mesma coisa repetidamente:

R
# Repeat 10 The code for this
sales <- c(120, 150, 80, 200, 175)
total <- sum(sales)
avg <- mean(sales)
top <- max(sales)
cat("Total Sales:", total, "Average:", avg, "Highest:", top, "\n")

10 operações de copiar e colar = 200 linhas de código duplicado. Se você precisar alterar a lógica em um lugar, terá que alterá-la em 10 lugares — mais cedo ou mais tarde, você vai deixar passar alguma coisa.

(2) Resolução de funções

R
# Write a function (just write 1 time)
report <- function(x) {
  cat("Total Sales:", sum(x), " Average:", mean(x), " Highest:", max(x), "\n")
}

# Call 10 times (Every time 1 row)
report(c(120, 150, 80, 200, 175))
report(c(80, 90, 100))
report(c(1000, 2000, 3000))

5 linhas de código de função + 10 linhas de chamadas = 15 linhas de código. Para alterar a lógica, basta uma única modificação. Esse é o poder das funções.



3. function(){}: Sintaxe básica

(1) Definição da função

R
# The Simplest Function
greet <- function() {
  cat("Hello, World!\n")
}

# Call
greet()
# Output:Hello, World!

(2) Funções com parâmetros

R
# Single parameter
greet <- function(name) {
  cat("Hello,", name, "!\n")
}

greet("Alice")
# Output:Hello, Alice !

# Multiple parameters
greet_full <- function(name, age) {
  cat("I am", name, ",This year", age, "yrs\n")
}

greet_full("Bob", 25)
# Output:I am Bob ,This year 25 yrs

(3) Diferenças entre funções em R e Python

Recurso R Python
definição function(x) { ... } def func(x):
Bloco de código {} Recuo
Valor de retorno A última linha é retornada automaticamente Requer return
Documentação Começa com #' (roxygen2) docstring
Declaração de tipo Nenhuma (tipagem dinâmica) Opcional (Python 3.5+)
R
# R the special:The last line wraps automatically(Not necessary return)
add <- function(a, b) {
  a + b   # The last line wraps automatically
}

result <- add(3, 4)
result
# [1] 7


4. 4 Tipos de parâmetros

(1) Parâmetros de posição x parâmetros nomeados

R
# Function Definition:3 parameter
power <- function(base, exp, mod) {
  result <- (base ^ exp) %% mod
  return(result)
}

# Location Parameters(In order)
power(2, 10, 1000)
# [1] 24  ← 2^10=1024, 1024 %% 1000 = 24

# Named parameters(By Name,Out of order)
power(mod = 1000, base = 2, exp = 10)
# [1] 24  ← The same result
💡 Dica: Quando há vários parâmetros, recomenda-se usar parâmetros nomeados para facilitar a leitura.

(2) Parâmetros padrão

R
# The second parameter has a default value.
power <- function(base, exp = 2, mod = 1000) {
  result <- (base ^ exp) %% mod
  return(result)
}

# Do not pass a second parameter,Use the default exp = 2
power(10)
# [1] 100  ← 10^2=100, 100 %% 1000 = 100

# Partial Parameter Passing
power(10, mod = 100)
# [1] 0  ← 10^2=100, 100 %% 100 = 0

(3) Regras para a ordem dos parâmetros

Regras de correspondência de parâmetros do R:

100%
graph TB
    A[Function Call power 10 exp=3] --> B[1. Exact Match for Named Parameters]
    B --> C[2. Prefix Matching]
    C --> D[3. Location Matching]
    
    style A fill:#fff3cd
    style B fill:#d4edda
    style C fill:#d4edda
    style D fill:#d4edda
  1. Correspondência exata: exp = 3 (a mais específica)
  2. Correspondência de prefixos: e = 3exp (menos teclas digitadas)
  3. Correspondência de posições: Primeiro parâmetro sem nome → base (menos seguro)
💡 Dica: Use correspondências exatas no código de produção (exp = 3). Digitar um pouco mais não economiza muito tempo, mas ajuda a evitar ambiguidades.

(4) Parâmetros variáveis ...

... significa “qualquer número de argumentos” e é comumente usado em funções wrapper:

R
# Use ... to accept any parameters
my_sum <- function(...) {
  args <- list(...)
  result <- sum(unlist(args))
  cat("Summed up", length(args), "parameter:", result, "\n")
  return(result)
}

my_sum(1, 2, 3)
# Summed up 3 parameter: 6

my_sum(10, 20, 30, 40, 50)
# Summed up 5 parameter: 150
💡 Dica: ... é muito usado ao encapsular outras funções (como quando um my_mean() personalizado encapsula alguns parâmetros de mean()).



5. 3 Tipos de valores de retorno

(1) A última linha quebra automaticamente

A última expressão em uma função R retorna automaticamente:

R
add <- function(a, b) {
  a + b   # Last line,Auto-Return
}

add(3, 4)
# [1] 7

(2) Explícito return()

R
# Use return() to return early
check_age <- function(age) {
  if (age < 0) {
    return("Age of Invalidity")  # Return Early
  }
  if (age >= 18) {
    return("Adulthood")
  }
  "Minor"  # Implicit Return
}

check_age(-5)   # [1] "Age of Invalidity"
check_age(20)   # [1] "Adulthood"
check_age(15)   # [1] "Minor"

(3) invisible(): Oculta o valor de retorno

invisible() Impedir que uma função imprima automaticamente seu valor de retorno (mas ainda permita que ele seja atribuído):

R
# Ordinary Functions
add_print <- function(a, b) {
  a + b  # It will print automatically
}

add_print(3, 4)
# [1] 7  ← Automatic Printing

# invisible Function
add_silent <- function(a, b) {
  invisible(a + b)  # Do not print automatically
}

add_silent(3, 4)
# No output  ← Do not print

# But it can still be assigned a value
result <- add_silent(3, 4)
result
# [1] 7  ← You can see it after the assignment.
💡 Dica: <- Atribuir um valor usando invisible()x <- 5 não exibe o resultado.



6. Funções anônimas: expressões lambda

O R suporta funções anônimas (funções sem nome):

R
# Ordinary Functions
square <- function(x) x ^ 2
square(5)
# [1] 25

# Anonymous Functions(Use directly)
(function(x) x ^ 2)(5)
# [1] 25

# Common Use Cases for Anonymous Functions:lapply/sapply
numbers <- list(1, 2, 3, 4, 5)
result <- lapply(numbers, function(x) x ^ 2)
result
# [[1]] 1
# [[2]] 4
# [[3]] 9
# [[4]] 16
# [[5]] 25
💡 Dica: As funções anônimas são extremamente comuns na família de funções apply — abordaremos esse assunto em profundidade na Lição 8.



7. Funções como objetos (O cerne da programação funcional em R)

As funções no R são de “primeira classe”, o que significa que elas podem:

(1) Atribuição de um valor a uma variável

R
f <- function(x) x * 2
g <- f  # A function has two names

f(5)  # [1] 10
g(5)  # [1] 10  ← Equivalent

(2) Passado como parâmetro

R
# Functions that take other functions as arguments
apply_twice <- function(f, x) {
  f(f(x))
}

# Passing Different Functions
apply_twice(function(x) x + 1, 5)  # 5+1+1=7
apply_twice(function(x) x * 2, 5)  # 5*2*2=20

(3) Como valor de retorno

R
# A function that returns a function(Closure)
make_multiplier <- function(k) {
  function(x) x * k
}

# Creating Functions with Different Scales
double <- make_multiplier(2)
triple <- make_multiplier(3)

double(5)  # [1] 10
triple(5)  # [1] 15
💡 Dica: Funções como valores de retorno são um conceito central da “programação funcional” do R, e muitas funções do tidyverse (map() reduce()) fazem uso disso.



8. do.call(): Chamada dinâmica

do.call() Expandir uma lista/vetor em argumentos de função:

R
# Regular Call
sum(1, 2, 3, 4, 5)
# [1] 15

# do.call Call(The parameter is a list)
args <- list(1, 2, 3, 4, 5)
do.call(sum, args)
# [1] 15

# Practical Application:Dynamic Creation data.frame
col_names <- c("name", "age", "score")
col1 <- c("Alice", "Bob", "Charlie")
col2 <- c(25, 30, 35)
col3 <- c(95, 88, 92)

df <- do.call(data.frame, list(
  name = col1,
  age = col2,
  score = col3
))
print(df)
#       name age score
# 1    Alice  25    95
# 2      Bob  30    88
# 3 Charlie  35    92


9. Âmbito: Onde as variáveis são válidas?

O R utiliza escopo léxico:

R
# Global Variables
x <- 10

# Global variables can be accessed within a function.
read_x <- function() {
  cat("x =", x, "\n")  # Read the whole picture x
}
read_x()
# x = 10

# However, local variables within a function do not affect the global scope.
set_local <- function() {
  x <- 999  # Local variables
  cat("Inside a function x =", x, "\n")
}
set_local()
# Inside a function x = 999
cat("Global x =", x, "\n")
# Global x = 10  <- Global x unchanged
⚠️ Observação: Por padrão, as funções do R não podem modificar variáveis globais (ao contrário do Python global). Para modificá-las, use <<- (mas isso não é recomendado).



10. Exemplo completo: Funções da ferramenta de relatório de vendas

A seguir, apresentamos um exemplo de um fluxo de trabalho completo que reúne todos os recursos das funções abordados nesta aula.

▶ Exemplo: Funções da ferramenta de relatório de vendas

R 📖 Somente leitura
# ============================================
# Sales Report Tool Functions
# Features:Encapsulate Common Analytical Logic,Reuse
# ============================================

# 1. Basic Statistical Functions(Back to List)
basic_stats <- function(x) {
  list(
    n = length(x),
    sum = sum(x),
    mean = round(mean(x), 2),
    median = median(x),
    sd = round(sd(x), 2),
    min = min(x),
    max = max(x)
  )
}

# 2. Formatted Output Functions(invisible Back)
print_report <- function(name, x) {
  stats <- basic_stats(x)
  cat("=================================\n")
  cat("Sales Report:", name, "\n")
  cat("=================================\n")
  cat("Sample size:", stats$n, "\n")
  cat("Total Sales:", stats$sum, "\n")
  cat("Average Sales:", stats$mean, "\n")
  cat("Median:", stats$median, "\n")
  cat("Standard Deviation:", stats$sd, "\n")
  cat("Minimum:", stats$min, " / Maximum:", stats$max, "\n")
  invisible(stats)  # Silent Return
}

# 3. Classification Function(Vectorization)
classify_sales <- function(x) {
  ifelse(x < 100, "Low",
  ifelse(x < 200, "Mid", "High"))
}

# 4. Main Program
sales_data <- list(
  "Beijing" = c(120, 150, 80, 200, 175),
  "Shanghai" = c(95, 110, 130, 145, 160),
  "Shenzhen" = c(200, 220, 180, 250, 300)
)

# Generate reports for each branch
for (city in names(sales_data)) {
  sales <- sales_data[[city]]
  print_report(city, sales)
  
  # Batch Classification Using Anonymous Functions
  levels <- sapply(sales, function(x) classify_sales(x))
  cat("\nCategory Summary:\n")
  print(table(levels))
  cat("\n")
}

# 5. Use do.call to merge all branches
all_sales <- do.call(c, sales_data)
cat("=== Company-wide Summary ===\n")
print_report("Company-wide", all_sales)
44 linhas de lógica (limite de 40, somente leitura)

Resultado esperado (trecho):

TEXT 📖 Somente leitura
=================================
Sales Report: Beijing
=================================
Sample size: 5
Total Sales: 725
Average Sales: 145
Median: 150
Standard Deviation: 47.7
Minimum: 80 / Maximum: 200

Category Summary:
levels
Mid High 
3  2 

=================================
Sales Report: Shanghai
=================================
...

❓ Perguntas Frequentes

P: As funções do R precisam usar return()? R: Não. A última expressão em uma função do R é retornada automaticamente; portanto, você pode usá-la sem escrever return(). No entanto, usar return() proporciona maior clareza, especialmente ao retornar antecipadamente a partir de uma condição if.

P: Onde os parâmetros padrão devem ser colocados? R: Os parâmetros padrão devem ser colocados após os parâmetros não padrão. function(a = 1, b) Isso é válido (primeiro os parâmetros padrão, depois os não padrão), mas todos os parâmetros nomeados devem ser utilizados ao chamar a função.

P: Como se usa ...? R: ... significa “aceita qualquer número de parâmetros” e costuma ser usada para envolver outras funções. Por exemplo, my_mean <- function(x, ...) mean(x, na.rm = TRUE, ...) envolve os parâmetros adicionais de mean().

P: Uma função pode modificar variáveis globais? R: Por padrão, não. É possível usar <<- para fazer isso (não recomendado), mas isso contaminará o ambiente global. A boa prática é que as funções retornem apenas um valor e não modifiquem o estado externo.

P: Quando se deve usar funções anônimas? R: Elas são mais comumente usadas em funções como lapply(), sapply(), map(), etc.lapply(x, function(i) i^2). É mais conciso do que definir uma função primeiro e depois chamá-la.


📖 Resumo


📝 Exercícios

  1. Problema básico: Escreva uma função celsius_to_fahrenheit(c) que converta graus Celsius em graus Fahrenheit (fórmula: F = C × 9/5 + 32). Teste com os valores de entrada 0, 25 e 100 e verifique se os resultados são 32, 77 e 212.

  2. Problema básico: Escreva uma função circle_area(r) que calcule a área de um círculo (pi * r^2), arredondando para 2 casas decimais. Teste com r = 1, 2, 5.

  3. Problema básico: Escreva uma função greet(name = "World", greeting = "Hello") com parâmetros padrão que exiba “Hello, World!” ou “Hi, Alice!”, e teste três maneiras diferentes de chamá-la.

  4. Problema Avançado: Escreva uma função analyze_scores(scores) que receba um vetor de números e retorne uma lista contendo mean median max min pass_rate taxas de aprovação, utilizando invisible() para impedir a impressão automática. Após chamar a função, use result$pass_rate para acessar as taxas de aprovação.

  5. Desafio: Escreva uma função que retorne uma função make_power(n) que retorne function(x) x^n. Use make_power(2) para criar square, use make_power(3) para criar cube e teste square(5) = 25 e cube(3) = 27. Salve uma captura de tela.

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%