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
)
dadosAula 5 – Manipulação de dados e introdução à construção de gráficos no R
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.
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.
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.
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.
dados$desempenho <- ifelse(
dados$nota_r < 6, "baixo",
ifelse(dados$nota_r < 8, "intermediario", "alto")
)
dados[, c("nome", "nota_r", "desempenho")]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.
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"]
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.
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")]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"]
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.
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_ampliadosA 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"]
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.
monitorias <- c(2, 1, 3, 0, 1, 1, 0, 4, 2, 2, 3, 0)
dados2 <- cbind(dados, monitorias = monitorias)
dados2A 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"]
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.
aggregate(nota_r ~ turma, data = dados, FUN = mean)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:
aggregate(horas_estudo ~ linguagem, data = dados, FUN = mean)6.2 Agregando várias variáveis simultaneamente
aggregate(cbind(nota_r, horas_estudo, projetos) ~ turma, data = dados, FUN = mean)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"]
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.
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
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:
bases_por_turma$A7.2 Divisão por linguagem
bases_por_linguagem <- split(dados, dados$linguagem)
bases_por_linguagem$RIlustraçã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"]
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.
dados[dados$nota_r >= 8, ]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:
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().
subset(dados, nota_r >= 8)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.
subset(dados, frequencia >= 90 & projetos >= 3)8.3 Selecionando também colunas específicas
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"]
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.
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.
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().
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")]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"]
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 \]
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} \]
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.
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"]
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().
plot(dados$horas_estudo, dados$nota_r)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_estudono eixo horizontal;nota_rno eixo vertical.
11.2 Melhorando a apresentação do gráfico
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.
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.
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)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.
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.
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"
)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
hist(
dados$nota_r,
main = "Histograma da nota em R",
xlab = "Nota em R",
ylab = "Frequência",
col = "lightblue",
border = "white"
)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.
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.
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"]
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
- 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.
- 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"senota_r >= 9eprojetos >= 4;"bom"senota_r >= 7.5efrequencia >= 85;"regular"senota_r >= 6;"insuficiente"caso contrário.
Apresente apenas as colunas:
nomenota_rprojetosfrequenciaperfil_academico
Exercício 2
Selecione apenas os estudantes que satisfazem simultaneamente as condições:
turma == "A"oulinguagem == "R";horas_estudo >= 10;nota_r >= 7.
Em seguida, apresente somente as colunas:
nometurmalinguagemhoras_estudonota_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"sehoras_estudo < 8;"media"se8 <= horas_estudo < 12;"alta"sehoras_estudo >= 12.
Apresente apenas as colunas:
nomehoras_estudofaixa_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".