Aula 5 – Manipulação de dados e introdução à construção de gráficos no R

Autor

Prof. Marcelo Ribeiro

Objetivo da Aula

Compreender e aplicar operações essenciais de preparação e transformação de bases de dados em R, incluindo classificação de casos, junção, agregação, divisão, seleção, recodificação e criação de novas variáveis, além de introduzir a construção de gráficos básicos no R e seus principais parâmetros.

Comentário do professor

Nesta aula, partiremos diretamente das operações de manipulação de dados, pois os conceitos introdutórios sobre objetos, estruturas de dados e fluxo básico de trabalho em R já foram abordados nas aulas anteriores.

dados <- data.frame(
  id = 1:12,
  nome = c("Ana", "Bruno", "Carla", "Daniel", "Eva", "Felipe",
           "Giovana", "Heitor", "Isabela", "Joao", "Karen", "Lucas"),
  turma = c("A", "A", "B", "B", "A", "B", "A", "B", "A", "B", "A", "B"),
  linguagem = c("R", "Python", "R", "Python", "R", "Python",
                "Python", "R", "R", "Python", "R", "Python"),
  horas_estudo = c(12, 8, 15, 7, 11, 9, 6, 14, 13, 10, 16, 5),
  projetos = c(3, 1, 4, 1, 2, 2, 1, 5, 4, 3, 5, 1),
  nota_r = c(8.7, 6.1, 9.2, 5.8, 7.5, 6.9, 5.4, 9.5, 8.8, 7.2, 9.7, 4.9),
  frequencia = c(92, 85, 97, 78, 88, 83, 75, 99, 94, 86, 98, 72),
  stringsAsFactors = FALSE
)

dados
Comentário do professor

A função data.frame() cria uma base de dados em formato tabular. Cada argumento informado corresponde, em geral, a uma coluna. O parâmetro stringsAsFactors = FALSE indica que textos devem permanecer como caracteres, e não serem convertidos automaticamente em fatores.

Comentário do professor

Neste conjunto de dados, cada linha representa um caso ou unidade observacional, enquanto cada coluna representa uma variável associada a esses casos.

4. Classificar casos

Classificar casos significa atribuir rótulos, categorias ou perfis às observações com base em critérios previamente definidos.

4.1 Classificação simples com ifelse()

Vamos classificar os estudantes segundo a variável nota_r.

Execute este código
dados$desempenho <- ifelse(
  dados$nota_r < 6, "baixo",
  ifelse(dados$nota_r < 8, "intermediario", "alto")
)

dados[, c("nome", "nota_r", "desempenho")]
Comentário do professor

A função ifelse(teste, valor_se_verdadeiro, valor_se_falso) avalia uma condição lógica e devolve um resultado para cada elemento do vetor. Aqui: - teste: dados$nota_r < 6 e, depois, dados$nota_r < 8; - valor_se_verdadeiro: rótulo atribuído quando a condição é verdadeira; - valor_se_falso: rótulo alternativo quando a condição é falsa.

Comentário do professor

A expressão dados[, c("nome", "nota_r", "desempenho")] seleciona todas as linhas e apenas as colunas indicadas. O objeto c() concatena os nomes das colunas que queremos exibir.

Ilustração 4.1 – Ideia de classificação de casos

flowchart LR
A["nota_r < 6"] --> B["desempenho = baixo"]
C["6 <= nota_r < 8"] --> D["desempenho = intermediario"]
E["nota_r >= 8"] --> F["desempenho = alto"]

Comentário do professor

Essa operação transforma uma variável quantitativa em uma variável categórica interpretável. Essa estratégia é extremamente útil em relatórios, tabelas-resumo, gráficos e processos de segmentação.

4.2 Classificação por múltiplos critérios

Agora vamos construir uma classificação mais exigente, combinando nota_r e projetos.

Execute este código
dados$perfil <- ifelse(
  dados$nota_r >= 8 & dados$projetos >= 3, "forte",
  ifelse(dados$nota_r >= 6, "moderado", "fragil")
)

dados[, c("nome", "nota_r", "projetos", "perfil")]
Comentário do professor

O operador & significa “e” lógico, sendo usado para verificar se duas condições são satisfeitas simultaneamente. Assim, dados$nota_r >= 8 & dados$projetos >= 3 só será verdadeiro quando ambas as desigualdades forem verdadeiras para o mesmo caso.

Ilustração 4.2 – Classificação por mais de um critério

flowchart TD
A["nota_r >= 8 ?"] -->|Sim| B["projetos >= 3 ?"]
A -->|Não| C["nota_r >= 6 ?"]
B -->|Sim| D["perfil = forte"]
B -->|Não| E["perfil = moderado"]
C -->|Sim| E
C -->|Não| F["perfil = fragil"]

Ideia central

Classificar casos é uma etapa importante porque permite organizar indivíduos, eventos ou registros segundo critérios analíticos de interesse. Em aplicações reais, isso pode significar classificar pacientes por risco, clientes por perfil, municípios por desempenho ou estudantes por aproveitamento.

5. Juntar casos ou variáveis

Em análise de dados, é comum combinar bases de duas formas principais:

  • acrescentando novos casos, isto é, novas linhas;
  • acrescentando novas variáveis, isto é, novas colunas.

5.1 Juntando casos com rbind()

Suponha que uma nova turma tenha sido observada e agora desejamos incorporar esses novos estudantes à base original.

Execute este código
novos_casos <- data.frame(
  id = 13:15,
  nome = c("Marina", "Nicolas", "Olivia"),
  turma = c("C", "C", "C"),
  linguagem = c("R", "Python", "R"),
  horas_estudo = c(14, 9, 12),
  projetos = c(4, 2, 3),
  nota_r = c(9.0, 6.7, 8.4),
  frequencia = c(96, 84, 91),
  desempenho = c("alto", "intermediario", "alto"),
  perfil = c("forte", "moderado", "forte"),
  stringsAsFactors = FALSE
)

dados_ampliados <- rbind(dados, novos_casos)

dados_ampliados
Comentário do professor

A função rbind() significa row bind, isto é, “ligação por linhas”. Ela empilha um objeto abaixo do outro. Seus argumentos são os objetos a serem unidos, que precisam ter estrutura compatível.

Ilustração 5.1 – Empilhamento de casos com rbind()

flowchart TB
A["Base 1<br/>12 linhas x 10 colunas"] --> C["rbind()"]
B["Base 2<br/>3 linhas x 10 colunas"] --> C
C --> D["Base final<br/>15 linhas x 10 colunas"]

Comentário do professor

A função rbind() exige compatibilidade estrutural entre os objetos. Em particular, o número e a ordem das colunas devem ser coerentes entre as bases a serem empilhadas.

5.2 Juntando variáveis com cbind()

Agora suponha que tenhamos, para os mesmos estudantes, uma nova variável contendo o número de monitorias frequentadas.

Execute este código
monitorias <- c(2, 1, 3, 0, 1, 1, 0, 4, 2, 2, 3, 0)

dados2 <- cbind(dados, monitorias = monitorias)

dados2
Comentário do professor

A função cbind() significa column bind, isto é, “ligação por colunas”. Ela acrescenta novas colunas a um objeto existente. Os argumentos são os objetos que serão justapostos lado a lado.

Ilustração 5.2 – Junção de variáveis com cbind()

flowchart LR
A["Base original<br/>12 linhas x 10 colunas"] --> C["cbind()"]
B["Nova variável<br/>12 valores"] --> C
C --> D["Base final<br/>12 linhas x 11 colunas"]

Atenção

Ao usar cbind(), é fundamental garantir que a ordem das observações seja a mesma nos objetos envolvidos. Caso contrário, a nova variável poderá ser associada aos casos errados.

6. Agregar casos

Agregar casos significa resumir observações por grupos, produzindo informações sintéticas que ajudam a comparar padrões e comportamentos.

6.1 Agregação com aggregate()

Vamos calcular a média de nota_r por turma.

Execute este código
aggregate(nota_r ~ turma, data = dados, FUN = mean)
Comentário do professor

A função aggregate(formula, data, FUN) resume uma variável por grupos. - formula: define a variável resposta e a variável de agrupamento, como em nota_r ~ turma; - data: base onde estão as variáveis; - FUN: função resumo a ser aplicada, neste caso mean.

Agora, a média de horas de estudo por linguagem:

Execute este código
aggregate(horas_estudo ~ linguagem, data = dados, FUN = mean)

6.2 Agregando várias variáveis simultaneamente

Execute este código
aggregate(cbind(nota_r, horas_estudo, projetos) ~ turma, data = dados, FUN = mean)
Comentário do professor

Aqui, a função cbind() foi usada dentro de aggregate() para indicar que desejamos resumir simultaneamente várias variáveis numéricas.

Ilustração 6.1 – Agregação por grupos

flowchart LR
A["Base original<br/>várias linhas por turma"] --> B["aggregate(..., FUN = mean)"]
B --> C["Uma linha por grupo<br/>resumo por turma"]

Comentário do professor

A agregação reduz o nível de detalhe da base original, mas fornece uma visão resumida muito útil para comparação entre grupos. Em muitos contextos, essa é a forma mais natural de iniciar uma exploração descritiva.

7. Dividir bases de dados

Dividir bases significa separar um conjunto em subconjuntos menores com base em alguma variável categórica ou critério de interesse.

7.1 Divisão com split()

Vamos dividir a base por turma.

Execute este código
bases_por_turma <- split(dados, dados$turma)

bases_por_turma
$A
   id    nome turma linguagem horas_estudo projetos nota_r frequencia
1   1     Ana     A         R           12        3    8.7         92
2   2   Bruno     A    Python            8        1    6.1         85
5   5     Eva     A         R           11        2    7.5         88
7   7 Giovana     A    Python            6        1    5.4         75
9   9 Isabela     A         R           13        4    8.8         94
11 11   Karen     A         R           16        5    9.7         98
      desempenho   perfil
1           alto    forte
2  intermediario moderado
5  intermediario moderado
7          baixo   fragil
9           alto    forte
11          alto    forte

$B
   id   nome turma linguagem horas_estudo projetos nota_r frequencia
3   3  Carla     B         R           15        4    9.2         97
4   4 Daniel     B    Python            7        1    5.8         78
6   6 Felipe     B    Python            9        2    6.9         83
8   8 Heitor     B         R           14        5    9.5         99
10 10   Joao     B    Python           10        3    7.2         86
12 12  Lucas     B    Python            5        1    4.9         72
      desempenho   perfil
3           alto    forte
4          baixo   fragil
6  intermediario moderado
8           alto    forte
10 intermediario moderado
12         baixo   fragil
Comentário do professor

A função split(x, f) divide um objeto x em subconjuntos definidos por f. - x: objeto a ser dividido; - f: fator, grupo ou variável categórica que define a partição.

Acessando apenas a turma A:

Execute este código
bases_por_turma$A

7.2 Divisão por linguagem

Execute este código
bases_por_linguagem <- split(dados, dados$linguagem)

bases_por_linguagem$R

Ilustração 7.1 – Divisão da base com split()

flowchart TD
A["Base completa"] --> B["split(..., turma)"]
B --> C["Subconjunto turma A"]
B --> D["Subconjunto turma B"]

Comentário do professor

A divisão de bases é especialmente útil quando queremos aplicar a mesma rotina analítica a grupos distintos, como turmas, regiões, categorias de produtos ou perfis de indivíduos.

8. Selecionar casos

Selecionar casos significa filtrar observações com base em condições lógicas.

8.1 Seleção com indexação lógica

Vamos selecionar os estudantes com nota em R maior ou igual a 8.

Execute este código
dados[dados$nota_r >= 8, ]
Comentário do professor

Na sintaxe objeto[linhas, colunas], a parte antes da vírgula controla quais linhas serão selecionadas e a parte depois da vírgula controla quais colunas serão mantidas. Quando deixamos o espaço das colunas vazio, estamos pedindo todas as colunas.

Agora, estudantes com frequência maior ou igual a 90 e pelo menos 3 projetos:

Execute este código
dados[dados$frequencia >= 90 & dados$projetos >= 3, ]

8.2 Seleção com subset()

A mesma operação pode ser escrita de forma mais legível com subset().

Execute este código
subset(dados, nota_r >= 8)
Comentário do professor

A função subset(x, subset, select) facilita a seleção de linhas e colunas. - x: base de dados; - subset: condição lógica para filtrar linhas; - select: colunas que se deseja manter, quando necessário.

Execute este código
subset(dados, frequencia >= 90 & projetos >= 3)

8.3 Selecionando também colunas específicas

Execute este código
subset(dados, nota_r >= 8, select = c(nome, turma, nota_r, projetos))

Ilustração 8.1 – Seleção de casos

flowchart LR
A["Base completa"] --> B["Filtro lógico<br/>nota_r >= 8"]
B --> C["Subconjunto com menos linhas"]

Comentário do professor

Selecionar casos é uma das operações mais frequentes em qualquer fluxo de análise de dados. Em geral, trabalhamos menos com a base inteira e mais com subconjuntos que atendem a critérios específicos.

9. Recodificar valores

Recodificar significa substituir valores originais por novos códigos, categorias ou níveis interpretativos.

9.1 Recodificação binária

Vamos transformar a variável linguagem em uma codificação binária:

  • 1 para R;
  • 0 para Python.
Execute este código
dados$linguagem_bin <- ifelse(dados$linguagem == "R", 1, 0)

dados[, c("nome", "linguagem", "linguagem_bin")]

9.2 Recodificação em faixas

Agora vamos recodificar a frequência em três níveis:

  • baixa: menor que 80;
  • media: de 80 a menos de 90;
  • alta: 90 ou mais.
Execute este código
dados$faixa_frequencia <- ifelse(
  dados$frequencia < 80, "baixa",
  ifelse(dados$frequencia < 90, "media", "alta")
)

dados[, c("nome", "frequencia", "faixa_frequencia")]

9.3 Recodificação com cut()

Outra forma muito útil de criar faixas é usar cut().

Execute este código
dados$faixa_nota <- cut(
  dados$nota_r,
  breaks = c(-Inf, 6, 8, Inf),
  labels = c("baixo", "intermediario", "alto"),
  right = FALSE
)

dados[, c("nome", "nota_r", "faixa_nota")]
Comentário do professor

A função cut(x, breaks, labels, right) divide uma variável quantitativa em intervalos. - x: vetor numérico a ser categorizado; - breaks: pontos de corte; - labels: nomes das categorias criadas; - right: define se o intervalo é fechado à direita (TRUE) ou à esquerda (FALSE).

Ilustração 9.1 – Recodificação de valores

flowchart LR
A["Valores originais<br/>75, 83, 98"] --> B["Regra de recodificação"]
B --> C["Categorias<br/>baixa, media, alta"]

Comentário do professor

A recodificação é uma operação central quando precisamos simplificar variáveis, construir indicadores ou preparar dados para tabelas, gráficos, relatórios e modelos.

10. Calcular novas variáveis

Criar novas variáveis significa produzir informações derivadas a partir das variáveis já existentes na base.

10.1 Nova variável aritmética

Vamos criar uma pontuação simples que combine nota e número de projetos:

\[ \text{score}_i = \text{nota\_r}_i + 0.5 \times \text{projetos}_i \]

Execute este código
dados$score <- dados$nota_r + 0.5 * dados$projetos

dados[, c("nome", "nota_r", "projetos", "score")]

10.2 Nova variável relativa

Também podemos construir uma medida de eficiência, dada por:

\[ \text{eficiencia}_i = \frac{\text{nota\_r}_i}{\text{horas\_estudo}_i} \]

Execute este código
dados$eficiencia <- dados$nota_r / dados$horas_estudo

dados[, c("nome", "nota_r", "horas_estudo", "eficiencia")]

10.3 Variável lógica

É muito comum também criar indicadores lógicos.

Execute este código
dados$alto_desempenho <- dados$nota_r >= 8

dados[, c("nome", "nota_r", "alto_desempenho")]

Ilustração 10.1 – Criação de nova variável

flowchart LR
A["nota_r"] --> C["Cálculo"]
B["projetos"] --> C
C --> D["score"]

Ideia central

Em muitas análises, a variável mais relevante não está originalmente disponível na base. Ela precisa ser construída a partir de combinações, razões, escores ou transformações das variáveis existentes.

11. Exemplo de um gráfico no R e seus parâmetros

Depois de manipular e organizar a base de dados, é natural passar para a representação gráfica.

11.1 Gráfico de dispersão básico

Vamos começar com um gráfico de dispersão usando a função plot().

Execute este código
plot(dados$horas_estudo, dados$nota_r)

Comentário do professor

A função plot(x, y, ...) constrói, no caso mais básico, um gráfico entre duas variáveis. - x: valores do eixo horizontal; - y: valores do eixo vertical; - ...: parâmetros gráficos adicionais, como título, cor, símbolo e tamanho.

Esse gráfico relaciona:

  • horas_estudo no eixo horizontal;
  • nota_r no eixo vertical.

11.2 Melhorando a apresentação do gráfico

Execute este código
plot(
  dados$horas_estudo,
  dados$nota_r,
  main = "Horas de estudo versus nota em R",
  xlab = "Horas de estudo por semana",
  ylab = "Nota em R",
  pch = 19,
  col = "blue",
  cex = 1.2
)

Principais parâmetros usados

  • main: título do gráfico;
  • xlab: rótulo do eixo x;
  • ylab: rótulo do eixo y;
  • pch: símbolo do ponto;
  • col: cor;
  • cex: tamanho dos pontos.
Comentário do professor

A função plot() é uma das mais importantes do R base. Mesmo em sua forma mais simples, ela já permite construir visualizações muito úteis e flexíveis.

11.3 Acrescentando uma linha de tendência

Vamos ajustar uma reta simples e adicioná-la ao gráfico.

Execute este código
modelo <- lm(nota_r ~ horas_estudo, data = dados)

plot(
  dados$horas_estudo,
  dados$nota_r,
  main = "Horas de estudo versus nota em R",
  xlab = "Horas de estudo por semana",
  ylab = "Nota em R",
  pch = 19,
  col = "blue",
  cex = 1.2
)

abline(modelo, col = "red", lwd = 2)

Comentário do professor

A função lm(formula, data) ajusta um modelo linear. - formula: relação a ser modelada, como nota_r ~ horas_estudo; - data: base onde as variáveis estão.

Comentário do professor

A função abline(a, b, ...) ou abline(modelo, ...) adiciona uma reta ao gráfico. Quando passamos um modelo linear como argumento, o R utiliza automaticamente os coeficientes ajustados dessa reta.

Novos parâmetros

  • abline(modelo, ...): adiciona a reta ajustada;
  • lwd: controla a espessura da linha.

11.4 Exemplo com gráfico de barras

Agora vamos construir um gráfico de barras com a média da nota por turma.

Execute este código
media_turma <- aggregate(nota_r ~ turma, data = dados, FUN = mean)

barplot(
  media_turma$nota_r,
  names.arg = media_turma$turma,
  main = "Média da nota em R por turma",
  xlab = "Turma",
  ylab = "Média da nota",
  col = "gray70",
  border = "gray30"
)

Comentário do professor

A função barplot(height, names.arg, ...) constrói um gráfico de barras. - height: alturas das barras; - names.arg: nomes exibidos abaixo das barras; - ...: parâmetros gráficos adicionais.

Parâmetros importantes do barplot()

  • names.arg: nomes exibidos abaixo das barras;
  • col: cor das barras;
  • border: cor da borda.

11.5 Exemplo com histograma

Execute este código
hist(
  dados$nota_r,
  main = "Histograma da nota em R",
  xlab = "Nota em R",
  ylab = "Frequência",
  col = "lightblue",
  border = "white"
)

Comentário do professor

A função hist(x, ...) constrói um histograma. - x: variável numérica; - ...: parâmetros gráficos, como título, rótulos e cores.

Comentário do professor

Mesmo em gráficos simples, a escolha de títulos, eixos, cores, símbolos e escalas faz diferença na clareza e na qualidade final da comunicação dos resultados.

12. Integração entre manipulação e visualização

Em uma análise real, manipulação e visualização não aparecem como etapas isoladas. Em geral, primeiro transformamos os dados e só depois representamos os resultados.

Vamos ver um exemplo integrado.

Execute este código
dados_filtrados <- subset(dados, frequencia >= 80)

dados_filtrados$grupo_nota <- ifelse(
  dados_filtrados$nota_r < 6, "baixo",
  ifelse(dados_filtrados$nota_r < 8, "intermediario", "alto")
)

tab <- aggregate(nota_r ~ grupo_nota, data = dados_filtrados, FUN = mean)

barplot(
  tab$nota_r,
  names.arg = tab$grupo_nota,
  main = "Nota média por grupo de desempenho",
  xlab = "Grupo",
  ylab = "Nota média",
  col = c("gray80", "gray60", "gray40")
)

Ilustração 12.1 – Fluxo integrado de manipulação e visualização

flowchart LR
A["Base original"] --> B["Selecionar casos"]
B --> C["Recodificar"]
C --> D["Agregar"]
D --> E["Representar graficamente"]

Comentário do professor

Esse exemplo ilustra um fluxo muito comum em Estatística e Ciência de Dados: selecionar casos, recodificar variáveis, agregar informações e representar o resultado graficamente.

13. Erros comuns e boas práticas

Erros comuns
  • usar cbind() sem garantir compatibilidade entre a ordem dos casos;
  • usar rbind() em bases com estruturas diferentes;
  • recodificar valores sem documentar o critério utilizado;
  • criar novas variáveis sem verificar coerência com as variáveis originais;
  • produzir gráficos sem título, sem rótulos de eixo ou com apresentação pouco legível.
Boas práticas
  • sempre verifique a estrutura da base antes e depois das transformações;
  • documente os critérios de classificação e recodificação;
  • dê nomes claros às novas variáveis;
  • revise se a transformação feita respeita o significado dos dados;
  • construa gráficos com títulos e eixos informativos.

14. Exercícios propostos

Exercício 1

Crie uma nova variável chamada perfil_academico segundo as regras abaixo:

  • "excelente" se nota_r >= 9 e projetos >= 4;
  • "bom" se nota_r >= 7.5 e frequencia >= 85;
  • "regular" se nota_r >= 6;
  • "insuficiente" caso contrário.

Apresente apenas as colunas:

  • nome
  • nota_r
  • projetos
  • frequencia
  • perfil_academico

Exercício 2

Selecione apenas os estudantes que satisfazem simultaneamente as condições:

  • turma == "A" ou linguagem == "R";
  • horas_estudo >= 10;
  • nota_r >= 7.

Em seguida, apresente somente as colunas:

  • nome
  • turma
  • linguagem
  • horas_estudo
  • nota_r

Exercício 3

Agregue, por turma, as seguintes medidas:

  • média de nota_r;
  • média de horas_estudo;
  • soma de projetos.

Apresente o resultado final em um único objeto.

Exercício 4

Divida a base segundo a variável linguagem e, em seguida, calcule a média de nota_r apenas para o subconjunto dos estudantes que preferem Python.

Exercício 5

Recodifique a variável horas_estudo em uma nova variável chamada faixa_estudo, com as categorias:

  • "baixa" se horas_estudo < 8;
  • "media" se 8 <= horas_estudo < 12;
  • "alta" se horas_estudo >= 12.

Apresente apenas as colunas:

  • nome
  • horas_estudo
  • faixa_estudo

Exercício 6

Crie uma nova variável chamada indice_global, definida por

\[ \text{indice\_global}_i = 0.6 \times \text{nota\_r}_i + 0.2 \times \text{projetos}_i + 0.02 \times \text{frequencia}_i \]

Em seguida, ordene a base em ordem decrescente de indice_global e apresente apenas os 5 primeiros casos.

Exercício 7

Construa um gráfico de dispersão entre horas_estudo e nota_r, com:

  • título "Relação entre horas de estudo e nota em R";
  • rótulos adequados nos eixos;
  • pontos na cor "darkred";
  • símbolo pch = 16;
  • tamanho cex = 1.2.

Depois, adicione ao gráfico a reta de regressão linear ajustada, na cor "navy" e com espessura lwd = 2.

Exercício 8

Agregue a média de nota_r por faixa_estudo e construa um gráfico de barras com:

  • título adequado;
  • nomes das categorias no eixo horizontal;
  • barras na cor "gray60";
  • bordas na cor "black".