---
# Só mude aqui!!!!
author: "Marco Antônio e Matheus Villela"
title: "Relatório 02 - Aula prática 02"
bibliography: referencias.bib
# A partir daqui nao faca alteracoes!!!!!
link-citations: true
csl: associacao-brasileira-de-normas-tecnicas-ipea.csl
subtitle: "<a href='https://bendeivide.github.io/courses/eait/' target='_blank'>Estatística Aplicada a Inovações Tecnológicas (UFSJ)</a> </br> <a href='https://bendeivide.github.io' target='_blank'>Prof. Ben Dêivide (DEFIM/CAP/UFSJ)</a>"
include-before-body: header.html
date: now
date-format: "DD/MM/YYYY, HH:mm"
lang: pt-BR
format:
html:
toc: true
toc-title: "Sumário" # Define o nome do sumário
toc-location: left # Coloca o sumário no lado esquerdo (opcional)
number-sections: true
theme: bootstrap
#css: styles.css
code-fold: true
code-tools: true
execute:
echo: true
warning: false
message: false
---
# 📌 Introdução
No **controle tecnológico do concreto**, a qualidade das decisões técnicas depende diretamente da confiabilidade dos dados coletados em campo e em laboratório. Contudo, na prática profissional, é comum que bases de dados apresentem inconsistências, como **valores ausentes, erros de digitação, padronização inadequada de categorias e registros incompatíveis com a realidade física do concreto**. Esses problemas, quando não tratados adequadamente, podem comprometer as análises estatísticas e levar a interpretações equivocadas.
Esta atividade simula uma situação real em que o engenheiro recebe uma **base de dados bruta contendo 100 registros e 10 variáveis relacionadas ao concreto**. Utilizando a linguagem **R, com ênfase nos recursos do Base R**, o trabalho consiste em **inspecionar, diagnosticar, limpar e explorar os dados**, transformando informações inconsistentes em dados confiáveis para auxiliar na tomada de decisão no contexto da **Engenharia Civil**.
# 🎯 Objetivo geral
Inspecionar, diagnosticar, limpar e explorar uma base de dados do **controle tecnológico do concreto** utilizando o **R (Base R)**, transformando dados brutos e inconsistentes em informações confiáveis para a **tomada de decisão técnica no âmbito da Engenharia Civil**.
## Objetivos específicos
* **Conhecer a estrutura da base**, identificando o número de observações, variáveis, tipos de dados e valores ausentes.
* **Diagnosticar problemas**, como erros de digitação, separadores decimais incorretos, categorias despadronizadas e valores incompatíveis com o contexto da Engenharia Civil.
* **Padronizar e limpar os dados**, corrigindo variáveis qualitativas e quantitativas, tratando valores ausentes e criando uma versão limpa da base.
* **Explorar os dados tratados** por meio de estatísticas descritivas e análises agrupadas por obra, tipo de concreto e idade.
* **Criar variáveis derivadas com interpretação técnica**, como resistência relativa, classificação de desempenho e indicador de desempenho acima da média.
* **Aplicar funções do Base R**, como `split()`, `lapply()`, `sapply()`, `apply()`, `aggregate()`, `for` e `if`, para o processamento e a análise dos dados.
* **Responder questões práticas da Engenharia Civil**, como a comparação de desempenho entre blocos e a relação entre diferentes variáveis do concreto.
* **Documentar e justificar as decisões de limpeza e análise**, garantindo maior rastreabilidade e reprodutibilidade dos procedimentos realizados.
* **Desenvolver um script organizado e comentado** que execute todo o fluxo de trabalho, desde a inspeção inicial até a geração de estatísticas e variáveis derivadas.
# ⚙️ Metodologia
A metodologia adotada neste trabalho consiste no **processamento completo de uma base de dados do controle tecnológico do concreto**, utilizando a linguagem **R**, com ênfase nos recursos disponíveis no **Base R**.
O fluxo de trabalho segue uma sequência lógica composta pelas etapas de:
1. **Importação dos dados**;
2. **Inspeção inicial da base**;
3. **Diagnóstico de inconsistências**;
4. **Limpeza e padronização dos dados**;
5. **Tratamento dos valores ausentes**;
6. **Exploração estatística**;
7. **Criação de variáveis derivadas**;
8. **Aplicação de funções de processamento**;
9. **Interpretação dos resultados sob a perspectiva da Engenharia Civil**.
As etapas foram organizadas em **35 questões**, que orientam o desenvolvimento progressivo da atividade.
## 📋 Etapas de desenvolvimento
**Questão 01 — Importação dos dados**
Importe a base de dados para o R e atribua-a ao objeto `dados`, verificando a correta importação.
**Questão 02 — Dimensões da base**
Determine as dimensões da base, identificando o número de **observações (linhas)** e **variáveis (colunas)**.
**Questão 03 — Estrutura da base**
Apresente a estrutura completa da base utilizando a função `str()` e analise detalhadamente o resultado obtido.
**Questão 04 — Resumo estatístico**
Gere um resumo estatístico das variáveis com a função `summary()` e identifique informações que merecem atenção.
**Questão 05 — Classificação das variáveis**
Classifique as variáveis em **quantitativas** e **qualitativas**, com base na estrutura apresentada pelo R.
**Questão 06 — Valores ausentes**
Verifique a existência de **valores ausentes (*missing values*)**, identificando a quantidade, as variáveis e as observações afetadas.
**Questão 07 — Valores incompatíveis**
Verifique valores incompatíveis com o contexto da Engenharia Civil nas variáveis `idade_dias`, `resistencia_mpa`, `abatimento_mm`, `densidade_kg_m3`, `relacao_a_c` e `absorção_agregado_pct`, criando códigos para a localização das observações problemáticas.
**Questão 08 — Erros de digitação**
Localize possíveis **erros de digitação** e apresente os registros completos das observações afetadas.
**Questão 09 — Padronização da variável `obra`**
Verifique a padronização das categorias da variável `obra` e identifique possíveis inconsistências.
**Questão 10 — Padronização da variável `tipo_concreto`**
Verifique a padronização das categorias da variável `tipo_concreto` e identifique categorias que representam o mesmo tipo de concreto com **grafias diferentes**.
**Questão 11 — Reavaliação dos tipos**
Reavalie os tipos das variáveis após a identificação dos problemas e reflita sobre como **um único valor digitado incorretamente pode alterar a interpretação de uma variável inteira pelo R**.
**Questão 12 — Cópia da base original**
Crie uma cópia da base original chamada `dados_limpos` e discuta a importância de **preservar a base original** durante o processo de tratamento dos dados.
**Questão 13 — Correção das variáveis qualitativas**
Corrija os problemas encontrados nas variáveis qualitativas, **padronizando suas categorias**.
**Questão 14 — Conversão das variáveis quantitativas**
Converta para o tipo adequado as variáveis que deveriam ser quantitativas e verifique se a conversão foi realizada corretamente.
**Questão 15 — Tratamento dos valores ausentes**
Identifique os valores ausentes e discuta os procedimentos mais adequados para cada situação, considerando **exclusão, substituição, manutenção do `NA` ou consulta à fonte original**. Justifique tecnicamente as decisões adotadas.
**Questão 16 — Reavaliação da base limpa**
Reavalie a estrutura (`str()`) e o resumo (`summary()`) da base limpa e compare os resultados obtidos com aqueles observados na **base original**.
**Questão 17 — Resistência média**
Calcule a **resistência média à compressão** dos corpos de prova globalmente e por bloco da obra, tipo de concreto e idade do corpo de prova.
**Questão 18 — Maior e menor resistência média**
Identifique o bloco da obra que apresenta a **maior e a menor resistência média**, apresentando os códigos utilizados para essa identificação.
**Questão 19 — Resistência por classe de concreto**
Calcule a resistência média para cada classe de concreto (**C25, C30, C35 e C40**) e identifique a classe que apresenta a **maior resistência média**.
**Questão 20 — Aplicação da função `aggregate()`**
Utilize a função `aggregate()` para obter a média das variáveis `resistencia_mpa`, `cimento_kg_m3`, `relacao_a_c`, `abatimento_mm` e `densidade_kg_m3` para cada tipo de concreto e interprete os resultados.
**Questão 21 — Resistência relativa**
Crie a variável `resistencia_relativa`, representando a razão entre a **resistência observada** e uma **resistência de referência associada à classe do concreto**, e explique como a referência foi definida.
**Questão 22 — Classificação do desempenho**
Crie a variável `classificacao`, classificando os corpos de prova segundo um critério relacionado à resistência, definindo e justificando tecnicamente os critérios utilizados.
**Questão 23 — Desempenho acima da média**
Crie a variável `acima_media`, indicando se a resistência do corpo de prova está **acima ou abaixo da resistência média de seu respectivo tipo de concreto**, utilizando os valores `TRUE` ou `FALSE`.
**Questão 24 — Aplicação da função `split()`**
Utilize a função `split()` para dividir a base de dados de acordo com a variável `tipo_concreto` e conte o **número de observações em cada grupo**.
**Questão 25 — Aplicação da função `lapply()`**
Utilizando a estrutura criada com `split()`, calcule a **resistência média de cada tipo de concreto** utilizando a função `lapply()`.
**Questão 26 — Aplicação da função `sapply()`**
Repita a operação utilizando `sapply()` e explique a diferença entre os resultados produzidos por `lapply()` e `sapply()`.
**Questão 27 — Aplicação da função `apply()` para médias**
Selecione as variáveis quantitativas relacionadas às propriedades do concreto e utilize a função `apply()` para calcular a **média de cada variável**.
**Questão 28 — Aplicação da função `apply()` por observação**
Utilize a função `apply()` para obter, para cada observação, uma **medida resumo envolvendo as variáveis quantitativas selecionadas** e discuta a interpretação física dessa medida.
**Questão 29 — Aplicação de `for` e `if`**
Utilizando `for` e `if` — **sem utilizar `ifelse()`** — percorra as 100 observações e identifique os corpos de prova cuja resistência está acima da **resistência média de sua respectiva classe de concreto**.
**Questão 30 — Abordagem vetorizada**
Repita a questão anterior utilizando uma **abordagem vetorizada** e compare as duas soluções quanto à simplicidade, legibilidade e eficiência, justificando sua análise.
**Questão 31 — Comparação entre blocos**
Verifique descritivamente a afirmação:
> **"Os concretos utilizados no Bloco C apresentam desempenho superior aos utilizados nos demais blocos."**
Realize a análise **sem utilizar teste de hipótese**.
**Questão 32 — Consumo de cimento e resistência**
Investigue a afirmação:
> **"Quanto maior o consumo de cimento, maior tende a ser a resistência do concreto."**
Identifique as variáveis que devem ser analisadas conjuntamente para avaliar essa relação.
**Questão 33 — Relação água/cimento e resistência**
Investigue a relação entre `relacao_a_c` e `resistencia_mpa`, analisando os padrões encontrados e interpretando os resultados considerando o **comportamento esperado do concreto**.
**Questão 34 — Evolução da resistência com a idade**
Compare a **resistência média dos concretos em diferentes idades** e analise a evolução da resistência com o aumento da idade dos corpos de prova.
**Questão 35 — Informações estatísticas relevantes**
Selecione e justifique as **cinco informações estatísticas mais importantes** para compor um relatório técnico destinado ao engenheiro responsável.
## 🏁 Etapa conclusiva — Script final
Como etapa conclusiva, desenvolva um **script final em R, organizado e comentado**, contemplando todo o fluxo de trabalho desenvolvido ao longo da atividade.
O script deverá contemplar:
1. **Inspeção inicial da base**;
2. **Identificação de problemas e inconsistências**;
3. **Verificação de valores ausentes**;
4. **Verificação e correção de inconsistências nas variáveis**;
5. **Produção de uma versão limpa dos dados**;
6. **Geração de estatísticas descritivas relevantes**;
7. **Criação de pelo menos duas variáveis derivadas**;
8. **Produção de informações úteis para auxiliar o engenheiro responsável pela obra**.
O código deverá ser estruturado de forma que **outro engenheiro consiga compreender as etapas realizadas**, permitindo a reprodução das análises e dos resultados obtidos.
Para isso, deverão ser utilizadas, sempre que pertinentes, as ferramentas de **Base R trabalhadas em sala de aula**, incluindo:
`str()`, `summary()`, `subset()`, `apply()`, `lapply()`, `sapply()`, `ifelse()`, `for`, `if`, `tapply()`, `aggregate()`, `split()`, `with()`, `by()`, `within()` e `ave()`.
# 📚 Fundamentação teórica
A **Estatística Descritiva** reúne métodos utilizados para organizar, resumir e apresentar dados, facilitando sua interpretação e permitindo uma compreensão inicial do comportamento de um conjunto de informações. Entre seus principais recursos estão as **medidas de posição**, como a média, e as **medidas de dispersão**, utilizadas para avaliar a variabilidade dos dados [@batista2024estatistica].
O **R** é uma linguagem de programação e ambiente computacional amplamente utilizado para **análise de dados e cálculos estatísticos**. O **Base R** disponibiliza diversas funções para manipulação, processamento e análise de dados, incluindo `summary()`, `mean()`, `apply()`, `lapply()` e `sapply()` [@batista2023rbasico].
Neste trabalho, esses conceitos são utilizados como **fundamentação para o desenvolvimento das análises estatísticas e computacionais** apresentadas nas etapas seguintes. A aplicação dessas ferramentas permite transformar uma base de dados inicialmente bruta em informações organizadas, interpretáveis e úteis para o **processo de tomada de decisão na Engenharia Civil**.
# 🔍 Resultados e Discussão
## Questão 1 — Importação dos dados
A base de dados foi importada para o R utilizando a função `read.csv()` e armazenada no objeto `dados`.
```{r}
# Importação da base de dados
dados <- read.csv("base_de_dados.csv",
header = TRUE,
sep = ";")
# Visualização das primeiras observações
head(dados)
```
O código utilizado foi dividido em duas etapas. Primeiramente, `read.csv()` realiza a **leitura do arquivo**, enquanto `header = TRUE` informa que a primeira linha contém os **nomes das variáveis**. O argumento `sep = ";"` define o **ponto e vírgula como separador das colunas**, conforme a estrutura do arquivo.
Em seguida, `head(dados)` apresenta as **primeiras observações da base**, permitindo verificar se os dados foram importados e organizados corretamente.
## Questão 2 — Dimensões da base
Para verificar o tamanho da base de dados, foi utilizada a função `dim()`, que retorna o número de **linhas e colunas** do objeto `dados`.
```{r}
# Verificação das dimensões da base
dim(dados)
```
A função `dim()` apresenta as dimensões no formato **(linhas, colunas)**. Portanto, o primeiro valor corresponde ao número de **observações**, enquanto o segundo representa o número de **variáveis**.
No caso da base analisada, o resultado foi **100 observações e 10 variáveis**, confirmando que a base possui **100 registros de corpos de prova**, distribuídos em 10 características.
## Questão 3 — Estrutura da base de dados
Para verificar a estrutura da base de dados, foi utilizada a função `str()`, que permite identificar o número de observações e variáveis, os nomes das colunas e os respectivos tipos de dados.
```{r}
str(dados)
```
A análise da estrutura permite verificar como o R interpretou cada variável e identificar possíveis problemas de importação ou classificação. As variáveis quantitativas devem estar armazenadas como numéricas (**"num"** ou **"int"**), enquanto as variáveis qualitativas, como categorias de obra e tipo de concreto, podem ser armazenadas como caracteres (**"chr"**).
Essa verificação é importante antes da realização das análises estatísticas, pois a classificação incorreta de uma variável pode interferir nos cálculos e na interpretação dos resultados.
## Questão 4 — Resumo estatístico da base de dados
Para obter uma visão geral das variáveis presentes na base de dados, foi utilizada a função `summary()`, que apresenta diferentes informações de acordo com o tipo de variável.
```{r}
summary(dados)
```
Para as **variáveis quantitativas**, a função apresenta medidas como mínimo, quartis, mediana, média e máximo. Para as **variáveis qualitativas**, são apresentadas as categorias existentes e suas respectivas frequências. Também são disponibilizadas informações sobre valores em branco e características das variáveis de texto.
A tabela abaixo apresenta um resumo dos resultados obtidos por meio dessa função:
| Informação apresentada | Tipo de variável | Significado |
| ---------------------- | ---------------- | ----------------------------------------------------- |
| **Length** | Qualitativa | Quantidade total de elementos da variável. |
| **N.unique** | Qualitativa | Número de valores ou categorias diferentes. |
| **Min.** | Quantitativa | Menor valor observado. |
| **1st Qu.** | Quantitativa | Primeiro quartil (25% dos dados). |
| **Median** | Quantitativa | Mediana (50% dos dados). |
| **Mean** | Quantitativa | Média dos valores. |
| **3rd Qu.** | Quantitativa | Terceiro quartil (75% dos dados). |
| **Max.** | Quantitativa | Maior valor observado. |
| **NA's** | Quantitativa | Quantidade de valores ausentes (*missing values*). |
| **n. blank** | Qualitativa | Quantidade de valores em branco. |
| **mincharn** | Qualitativa | Menor número de caracteres encontrados. |
| **maxcharn** | Qualitativa | Maior número de caracteres encontrados. |
Dessa forma, o `summary()` fornece uma visão inicial da estrutura e das características dos dados, permitindo verificar a distribuição das variáveis, suas frequências e a presença de valores ausentes.
## Questão 5 — Classificação das variáveis
Antes de verificar a classificação realizada pelo R, foram definidos os **tipos esperados para cada variável**, considerando sua natureza e seu significado no contexto do controle tecnológico do concreto. Assim, variáveis que representam categorias ou identificações são consideradas **qualitativas**, enquanto aquelas que representam medidas ou quantidades são consideradas **quantitativas**.
Para verificar como o R reconheceu cada variável, foi utilizada a função `sapply()` em conjunto com `class()`.
```{r}
# Verificação do tipo de cada variável
sapply(dados, class)
```
O resultado obtido foi:
| Variável | Tipo esperado | Tipo reconhecido pelo R | Classificação |
| ----------------------- | ------------- | ----------------------- | ------------- |
| `id_corpo_prova` | Qualitativa | `character` | Qualitativa |
| `obra` | Qualitativa | `character` | Qualitativa |
| `tipo_concreto` | Qualitativa | `character` | Qualitativa |
| `idade_dias` | Quantitativa | `integer` | Quantitativa |
| `resistencia_mpa` | Quantitativa | `character` | Qualitativa |
| `cimento_kg_m3` | Quantitativa | `character` | Qualitativa |
| `relacao_a_c` | Quantitativa | `character` | Qualitativa |
| `abatimento_mm` | Quantitativa | `numeric` | Quantitativa |
| `densidade_kg_m3` | Quantitativa | `numeric` | Quantitativa |
| `absorção_agregado_pct` | Quantitativa | `numeric` | Quantitativa |
A partir da estrutura apresentada pelo R, as variáveis **`id_corpo_prova`**, **`obra`** e **`tipo_concreto`** foram reconhecidas como `character`, estando de acordo com o esperado para variáveis qualitativas. Já **`idade_dias`**, **`abatimento_mm`**, **`densidade_kg_m3`** e **`absorção_agregado_pct`** foram reconhecidas como `integer` ou `numeric`, também de acordo com sua natureza quantitativa.
Entretanto, **`resistencia_mpa`**, **`cimento_kg_m3`** e **`relacao_a_c`** são quantitativas por sua natureza, mas foram reconhecidas pelo R como `character`. Essa divergência pode estar relacionada a **erros de digitação, caracteres inseridos nos valores ou separadores decimais inadequados**, fazendo com que o R interprete essas informações como texto.
Portanto, a estrutura apresentada pelo R permite identificar que essas três variáveis precisarão ser **corrigidas e convertidas para um formato quantitativo** nas etapas posteriores de limpeza da base.
## Questão 6 — Valores ausentes na base
Para verificar a existência de valores ausentes ou registros vazios na base, foram considerados tanto os valores `NA` quanto os principais padrões utilizados para representar dados não preenchidos: `""`, `" "`, `"NA"`, `"N/A"`, `"-"`, `"null"` e `"NULL"`.
```{r}
# Padrões considerados como valores ausentes
ausentes <- c("", " ", "NA", "N/A", "-", "null", "NULL")
# Quantidade total de valores ausentes ou vazios
sum(is.na(dados) | dados == "" | dados == " " |
dados == "NA" | dados == "N/A" | dados == "-" |
dados == "null" | dados == "NULL", na.rm = TRUE)
# Quantidade por variável
sapply(dados, function(x)
sum(is.na(x) | x %in% ausentes, na.rm = TRUE))
# Observações que apresentam valores ausentes ou vazios
which(apply(dados, 1, function(x)
any(is.na(x) | x %in% ausentes)))
```
O primeiro comando contabiliza o **total de valores ausentes ou vazios** encontrados na base. O segundo identifica **em quais variáveis esses registros aparecem**, enquanto o terceiro apresenta **as observações afetadas**.
Dessa forma, a análise não considera apenas os valores `NA` reconhecidos automaticamente pelo R, mas também registros preenchidos com diferentes formas de indicar ausência de informação.
### Investigação dos erros de preenchimento e padronização
Nesta etapa, foram investigados possíveis **erros de preenchimento e inconsistências de padronização** em todas as células da base. A análise buscou identificar automaticamente diferenças de escrita, caracteres inadequados, espaços desnecessários e formas diferentes de representação dos mesmos valores.
```{r}
# Remoção de espaços desnecessários
sapply(dados, function(x) sum(grepl("^ | $", x)))
# Identificação de categorias diferentes nas variáveis qualitativas
unique(dados$obra)
unique(dados$tipo_concreto)
# Identificação de valores que possuem vírgula decimal
sapply(dados, function(x) sum(grepl(",", x)))
# Identificação de valores contendo letras em variáveis quantitativas
variaveis_quantitativas <- c(
"idade_dias",
"resistencia_mpa",
"cimento_kg_m3",
"relacao_a_c",
"abatimento_mm",
"densidade_kg_m3",
"absorção_agregado_pct"
)
sapply(dados[variaveis_quantitativas], function(x)
sum(grepl("[A-Za-z]", x))
)
```
A investigação permitiu identificar **erros de preenchimento e diferenças de padronização** nas variáveis da base. Foram encontrados registros com **espaços adicionais**, diferenças de **maiúsculas e minúsculas**, utilização de **vírgula como separador decimal** e presença de **caracteres alfabéticos em variáveis que deveriam conter valores numéricos**.
Essas inconsistências podem fazer com que valores que representam a mesma informação sejam interpretados de maneiras diferentes pelo R.
## Questão 7 — Valores potencialmente incompatíveis
Nesta etapa, foram investigados valores que podem ser **incompatíveis ou suspeitos no contexto da Engenharia Civil**. Os critérios utilizados foram baseados, quando aplicável, em referências normativas e, nos demais casos, na identificação de valores que se afastam significativamente do padrão observado na própria base.
Para o **abatimento**, foi considerada a **ABNT NBR 16889:2020** [@abnt16889], que estabelece o método para determinação da consistência do concreto pelo abatimento do tronco de cone, em conjunto com as classes de abatimento estabelecidas pela **ABNT NBR 8953:2015** [@abnt8953].
Para a **resistência à compressão**, foi considerada a **ABNT NBR 5739:2018** [@abnt5739], que estabelece o método para determinação da resistência à compressão de corpos de prova cilíndricos de concreto. Como a norma não estabelece um intervalo universal de resistência válido para todos os concretos, os valores utilizados na triagem foram definidos a partir do contexto e do padrão observado na própria base.
Para **densidade e absorção**, foi considerada a **ABNT NBR 9778:2005** [@abnt9778], que estabelece métodos para determinação da absorção de água, índice de vazios e massa específica de argamassas e concretos endurecidos.
Para **idade dos corpos de prova** e **relação água/cimento**, foi realizada uma análise exploratória baseada nos valores observados na própria base, pois esses parâmetros dependem das condições de projeto, dosagem e programa experimental.
```{r}
# Valores potencialmente incompatíveis com o contexto dos dados
# Idade dos corpos de prova
dados[dados$idade_dias <= 0 | dados$idade_dias > 56, ]
# Resistência à compressão
dados[dados$resistencia_mpa < 20 | dados$resistencia_mpa > 60, ]
# Abatimento
dados[dados$abatimento_mm < 10 | dados$abatimento_mm > 220, ]
# Densidade
dados[dados$densidade_kg_m3 < 2000 | dados$densidade_kg_m3 > 2600, ]
# Relação água/cimento
dados[dados$relacao_a_c < 0.40 | dados$relacao_a_c > 0.70, ]
# Absorção
dados[dados$`absorção_agregado_pct` < 0 |
dados$`absorção_agregado_pct` > 10, ]
```
Os códigos acima realizam uma **triagem inicial**, permitindo localizar as observações que merecem investigação. Um valor identificado não deve ser automaticamente considerado incorreto, pois pode representar uma condição real de ensaio ou de dosagem.
Na base analisada, esses critérios permitem identificar, entre outros, **idade de 280 dias**, **abatimento de 1250 mm**, **densidade de 238 kg/m³** e **absorção de 18,4%**. Esses valores apresentam grande afastamento em relação aos demais registros e, portanto, devem ser conferidos antes da utilização da base nas análises estatísticas.
## Questão 8 — Possíveis erros de digitação
Nesta etapa, foram procurados valores que apresentam características de **erro de digitação ou preenchimento**, como uso incorreto de letras, separadores decimais, espaços desnecessários e categorias com grafia diferente das demais.
Para localizar esses problemas, foram utilizados códigos que verificam automaticamente padrões diferentes dos predominantes na base.
```{r}
# 1. Resistência com caracteres diferentes do padrão numérico
dados[!grepl("^[0-9]+([.,][0-9]+)?$", dados$resistencia_mpa), ]
# 2. Relação água/cimento com separador decimal diferente
dados[!grepl("^[0-9]+([.,][0-9]+)?$", dados$relacao_a_c), ]
# 3. Consumo de cimento com caracteres não numéricos
dados[!grepl("^[0-9]+([.,][0-9]+)?$", dados$cimento_kg_m3), ]
# 4. Categorias de obra com espaços no início ou no final
dados[trimws(dados$obra) != dados$obra, ]
# 5. Categorias de tipo de concreto diferentes do padrão
dados[!dados$tipo_concreto %in% c("C25", "C30", "C35", "C40"), ]
```
A aplicação dos códigos permite localizar os seguintes possíveis erros de preenchimento:
| Observação | Variável | Valor encontrado | Possível problema |
| ---------- | ----------------- | ---------------- | ---------------------------------------------- |
| **CP-008** | `resistencia_mpa` | `38,7` | Uso de vírgula como separador decimal |
| **CP-019** | `resistencia_mpa` | `3O,4` | Letra **O** utilizada no lugar do número **0** |
| **CP-027** | `obra` | `Bloco B ` | Espaço desnecessário ao final do texto |
| **CP-045** | `relacao_a_c` | `0,55` | Uso de vírgula como separador decimal |
| **CP-059** | `tipo_concreto` | `c30` | Categoria escrita com letra minúscula |
| **CP-064** | `cimento_kg_m3` | `390O` | Letra **O** utilizada no lugar do número **0** |
Além desses casos, os códigos permitem verificar a existência de outros registros com padrões diferentes sem que seja necessário conhecer previamente onde os problemas estão.
Os casos identificados representam **problemas de preenchimento ou padronização**, e não necessariamente erros nos valores físicos medidos. Por exemplo, `38,7` pode representar corretamente uma resistência de 38,7 MPa, mas está registrada utilizando vírgula decimal, enquanto os demais valores utilizam ponto.
O caso mais evidente de erro de digitação ocorre em **CP-019**, onde `3O,4` apresenta a letra **O** no lugar do número **0**, e em **CP-064**, onde `390O` apresenta o mesmo problema. Esses registros impedem que o R reconheça diretamente os valores como numéricos.
Os registros completos identificados são apresentados a seguir:
```{r}
# Apresentação dos registros completos com possíveis
# erros de digitação ou preenchimento
dados[c(8, 19, 27, 45, 59, 64), ]
```
Assim, foram identificados **seis registros que apresentam possíveis problemas de digitação ou padronização**, envolvendo as variáveis `resistencia_mpa`, `obra`, `relacao_a_c`, `tipo_concreto` e `cimento_kg_m3`.
## Questão 9 — Padronização da variável `obra`
Para verificar se todas as categorias da variável `obra` estão padronizadas, foram analisados os valores existentes e também removidos temporariamente os espaços no início e no final dos textos para comparação.
```{r}
# Verificação das categorias existentes
unique(dados$obra)
# Identificação de categorias que possuem espaços extras
dados[trimws(dados$obra) != dados$obra, ]
# Comparação das categorias após remoção dos espaços
unique(trimws(dados$obra))
```
A análise identificou uma inconsistência na variável `obra`. O registro **CP-027** apresenta a categoria:
```text
"Bloco B "
```
enquanto os demais registros correspondentes apresentam:
```text
"Bloco B"
```
A diferença está apenas na presença de um **espaço em branco ao final do texto**. Embora visualmente pareçam iguais, o R considera `"Bloco B "` e `"Bloco B"` como categorias diferentes.
Portanto, a variável `obra` **não está completamente padronizada**.
## Questão 10 — Padronização da variável `tipo_concreto`
Para verificar se as categorias da variável `tipo_concreto` estão padronizadas, foram observadas as categorias existentes e realizada uma comparação após a padronização temporária de letras maiúsculas e espaços.
```{r}
# Verificação das categorias existentes
unique(dados$tipo_concreto)
# Padronização temporária para comparação
tipo_padronizado <- toupper(trimws(dados$tipo_concreto))
# Identificação das categorias diferentes do padrão
dados[tipo_padronizado != dados$tipo_concreto, ]
# Verificação das categorias após a padronização
unique(tipo_padronizado)
```
A análise identificou uma inconsistência no registro **CP-059**, em que a variável `tipo_concreto` foi preenchida como:
```text
"c30"
```
enquanto os demais registros utilizam:
```text
"C30"
```
Nesse caso, `"c30"` e `"C30"` representam o **mesmo tipo de concreto**, porém foram escritos de maneiras diferentes devido ao uso de letra minúscula.
Portanto, a variável `tipo_concreto` **não está totalmente padronizada**.
## Questão 11 — Reavaliação dos tipos
Após a identificação dos problemas, os tipos das variáveis foram novamente verificados utilizando `sapply()` e `class()`.
```{r}
# Verificação dos tipos das variáveis
sapply(dados, class)
```
O resultado obtido permanece:
| Variável | Tipo reconhecido pelo R |
| ----------------------- | ----------------------- |
| `id_corpo_prova` | `character` |
| `obra` | `character` |
| `tipo_concreto` | `character` |
| `idade_dias` | `integer` |
| `resistencia_mpa` | `character` |
| `cimento_kg_m3` | `character` |
| `relacao_a_c` | `character` |
| `abatimento_mm` | `numeric` |
| `densidade_kg_m3` | `numeric` |
| `absorção_agregado_pct` | `numeric` |
O resultado permanece com `resistencia_mpa`, `cimento_kg_m3` e `relacao_a_c` como `character`, embora sejam variáveis quantitativas por sua natureza.
Isso ocorre porque **um único valor incompatível pode fazer com que o R interprete toda a coluna como texto**. Por exemplo, os valores `3O,4` e `390O` contêm a letra **O** no lugar do número **0**, impedindo que o R reconheça essas colunas diretamente como numéricas.
## Questão 12 — Cópia da base original
Foi criada uma cópia da base original para realizar as etapas de limpeza sem alterar os dados inicialmente importados.
```{r}
# Criação da cópia para limpeza
dados_limpos <- dados
```
É recomendável preservar a base original para **evitar a perda dos dados brutos**, permitir a **comparação entre os dados originais e os dados tratados** e possibilitar a **reversão ou revisão das decisões de limpeza**, garantindo maior rastreabilidade e segurança na análise.
## Questão 13 — Correção das variáveis qualitativas
Foram corrigidas as inconsistências identificadas nas variáveis qualitativas `obra` e `tipo_concreto`, padronizando espaços e letras maiúsculas.
```{r}
# Padronização das variáveis qualitativas
dados_limpos$obra <- trimws(dados_limpos$obra)
dados_limpos$tipo_concreto <- toupper(trimws(dados_limpos$tipo_concreto))
# Verificação das categorias após a correção
unique(dados_limpos$obra)
unique(dados_limpos$tipo_concreto)
```
A função `trimws()` remove espaços desnecessários no início e no final dos textos, enquanto `toupper()` transforma as letras em maiúsculas. Dessa forma, categorias como `"Bloco B "` e `"c30"` passam a ser representadas de forma padronizada como `"Bloco B"` e `"C30"`.
## Questão 14 - Correção das variáveis quantitativas
As variáveis quantitativas foram convertidas para o tipo numérico, corrigindo também os valores que apresentavam caracteres incompatíveis com esse formato.
```{r}
dados_limpos$idade_dias <- as.numeric(dados_limpos$idade_dias)
dados_limpos$resistencia_mpa <- as.numeric(
gsub(",", ".",
gsub("O", "0", dados_limpos$resistencia_mpa)
)
)
dados_limpos$cimento_kg_m3 <- as.numeric(
gsub("O", "0", dados_limpos$cimento_kg_m3)
)
dados_limpos$relacao_a_c <- as.numeric(
gsub(",", ".", dados_limpos$relacao_a_c)
)
dados_limpos$abatimento_mm <- as.numeric(dados_limpos$abatimento_mm)
dados_limpos$densidade_kg_m3 <- as.numeric(dados_limpos$densidade_kg_m3)
dados_limpos$`absorção_agregado_pct` <- as.numeric(
dados_limpos$`absorção_agregado_pct`
)
# Verificação
str(dados_limpos)
```
A função `str()` foi utilizada para confirmar que as variáveis passaram a ser reconhecidas pelo R como **numéricas (`num`)**.
## Questão 15 — Tratamento dos valores ausentes
Inicialmente, foram identificados os valores ausentes (`NA`) presentes na base e as respectivas variáveis afetadas.
```{r}
# Quantidade de valores ausentes por variável
sapply(dados_limpos, function(x) sum(is.na(x)))
# Localização das observações que possuem valores ausentes
dados_limpos[!complete.cases(dados_limpos), ]
```
A função `is.na()` identifica os valores ausentes e, em conjunto com `sum()`, permite contabilizar a quantidade de `NA` em cada variável. Já `complete.cases()` permite identificar as observações que possuem todos os valores preenchidos.
Como não é possível consultar a fonte original para recuperar os valores ausentes, optou-se pela **exclusão das observações que apresentam dados vazios**. Essa decisão evita a introdução de valores estimados ou artificiais na base, preservando a confiabilidade dos resultados.
Para preservar a base `dados_limpos` e permitir a comparação entre as versões, foi criada uma nova variável denominada `dados_sem_na`:
```{r}
# Criação de uma nova base sem observações com valores ausentes
dados_sem_na <- dados_limpos[complete.cases(dados_limpos), ]
# Verificação da quantidade de observações após a exclusão
nrow(dados_sem_na)
```
A função `complete.cases()` seleciona apenas as observações que não possuem valores ausentes. Dessa forma, `dados_sem_na` contém somente os registros completos, enquanto `dados_limpos` é mantida como referência para comparação.
A exclusão das observações foi adotada de forma criteriosa, considerando o impacto da perda de registros sobre o tamanho da amostra. Essa abordagem é preferível à substituição dos valores por média, mediana ou outros valores estimados, pois evita a criação de informações que não foram efetivamente observadas.
## Questão 16 — Reavaliação da base limpa
Após a correção das variáveis e a remoção das observações que apresentavam valores ausentes, foi realizada uma nova verificação da estrutura e do resumo estatístico da base `dados_sem_na`.
```{r}
# Verificação da estrutura da base sem valores ausentes
str(dados_sem_na)
# Verificação do resumo estatístico
summary(dados_sem_na)
```
Em relação à base original, as principais alterações foram a **correção dos tipos das variáveis que estavam classificadas de forma inadequada** e a **remoção das observações que apresentavam valores ausentes**.
Com isso, `dados_sem_na` apresenta uma estrutura mais adequada para as análises estatísticas seguintes, sem registros contendo `NA` nas variáveis analisadas. A quantidade de observações também foi reduzida em função da exclusão dos registros incompletos.
## Questão 17 — Resistência média
Para avaliar o desempenho dos corpos de prova, foi calculada inicialmente a resistência média à compressão considerando todos os registros da base. Em seguida, a média foi calculada separadamente por **bloco da obra**, **tipo de concreto** e **idade do corpo de prova**. Para isso, foi utilizada a função `aggregate()`, que permite calcular estatísticas resumidas para diferentes grupos de observações.
```{r}
aggregate(resistencia_mpa ~ obra + tipo_concreto + idade_dias,
data = dados_sem_na,
FUN = mean)
# Resistência média global
mean(dados_sem_na$resistencia_mpa)
# Resistência média por bloco
aggregate(resistencia_mpa ~ obra,
data = dados_sem_na,
FUN = mean)
# Resistência média por tipo de concreto
aggregate(resistencia_mpa ~ tipo_concreto,
data = dados_sem_na,
FUN = mean)
# Resistência média por idade
aggregate(resistencia_mpa ~ idade_dias,
data = dados_sem_na,
FUN = mean)
```
O primeiro cálculo apresenta a resistência média considerando simultaneamente o **bloco da obra, o tipo de concreto e a idade**. Em seguida, `mean()` calcula a resistência média global, enquanto `aggregate()` permite obter as médias separadamente para cada bloco, tipo de concreto e idade.
Essa análise permite comparar o desempenho dos corpos de prova sob diferentes condições e verificar como a **resistência à compressão varia entre as obras, classes de concreto e idades de ensaio**.
## Questão 18 — Comparação entre obras
Para identificar qual bloco da obra apresentou a **maior e a menor resistência média**, foram calculadas inicialmente as médias de resistência por bloco utilizando a função `aggregate()`. Em seguida, as funções `which.max()` e `which.min()` foram utilizadas para localizar, respectivamente, os blocos com a maior e a menor resistência média.
```{r}
media_obra <- aggregate(resistencia_mpa ~ obra,
data = dados_sem_na,
FUN = mean)
# Maior resistência média
media_obra[which.max(media_obra$resistencia_mpa), ]
# Menor resistência média
media_obra[which.min(media_obra$resistencia_mpa), ]
```
A função `aggregate()` calcula a **resistência média para cada bloco da obra** e armazena os resultados no objeto `media_obra`. A função `which.max()` identifica a posição da maior média, enquanto `which.min()` identifica a posição da menor média.
Dessa forma, os códigos permitem determinar diretamente **qual bloco apresentou o maior desempenho médio e qual apresentou o menor desempenho médio**, utilizando como critério a resistência à compressão dos corpos de prova.
## Questão 19 — Resistência média por classe de concreto
Para comparar o desempenho das diferentes classes de concreto, foi calculada a **resistência média à compressão** para as classes C25, C30, C35 e C40. Em seguida, foi identificada a classe que apresentou a maior resistência média.
```{r}
media_tipo <- aggregate(resistencia_mpa ~ tipo_concreto,
data = dados_sem_na,
FUN = mean)
# Resistência média de cada classe
media_tipo
# Classe com maior resistência média
media_tipo[which.max(media_tipo$resistencia_mpa), ]
```
A função `aggregate()` calcula a resistência média para cada classe de concreto, permitindo comparar o desempenho entre **C25, C30, C35 e C40**. Em seguida, a função `which.max()` identifica a classe que apresenta a **maior resistência média**.
Assim, a classe apresentada no último resultado corresponde ao **tipo de concreto com maior resistência média à compressão** na base analisada.
## Questão 20 — Utilizando `aggregate()`
Para analisar as características dos diferentes tipos de concreto, foram calculadas as médias de **resistência à compressão, consumo de cimento, relação água/cimento, abatimento e densidade** para cada classe de concreto. Para isso, foi utilizada a função `aggregate()`.
```{r}
aggregate(
cbind(resistencia_mpa,
cimento_kg_m3,
relacao_a_c,
abatimento_mm,
densidade_kg_m3) ~ tipo_concreto,
data = dados_sem_na,
FUN = mean
)
```
A função `aggregate()` permite calcular simultaneamente a média de várias variáveis quantitativas, agrupando os resultados pela variável `tipo_concreto`.
Os resultados permitem comparar as características médias das classes **C25, C30, C35 e C40**. A resistência média indica o desempenho mecânico de cada classe, enquanto o consumo médio de cimento mostra a quantidade de cimento utilizada por metro cúbico. A relação água/cimento permite avaliar a proporção entre água e cimento, sendo uma variável importante para o comportamento da resistência. O abatimento representa a consistência do concreto no estado fresco e a densidade indica sua massa por unidade de volume.
A comparação conjunta dessas médias permite verificar diferenças entre as classes de concreto e observar se os maiores valores de resistência estão associados a diferenças no **consumo de cimento e na relação água/cimento**, considerando também as características do concreto no estado fresco e endurecido.
## Questão 21 — Resistência relativa
A variável `resistencia_relativa` foi criada para comparar a resistência à compressão observada em cada corpo de prova com a **resistência de referência correspondente à sua classe de concreto**.
As resistências de referência foram definidas de acordo com a classe do concreto, considerando o valor numérico indicado pela própria classificação: **C25 = 25 MPa, C30 = 30 MPa, C35 = 35 MPa e C40 = 40 MPa**.
```{r}
# Definição da resistência de referência de acordo com a classe
resistencia_referencia <- ifelse(dados_sem_na$tipo_concreto == "C25", 25,
ifelse(dados_sem_na$tipo_concreto == "C30", 30,
ifelse(dados_sem_na$tipo_concreto == "C35", 35,
ifelse(dados_sem_na$tipo_concreto == "C40", 40, NA))))
# Cálculo da resistência relativa
dados_sem_na$resistencia_relativa <-
dados_sem_na$resistencia_mpa / resistencia_referencia
# Visualização dos resultados
dados_sem_na[, c("tipo_concreto", "resistencia_mpa", "resistencia_relativa")]
```
A resistência relativa foi calculada pela expressão:
$$
R_{rel} = \frac{R_{obs}}{R_{ref}}
$$ {#eq-resistencia_relativa}
em que \(R_{rel}\) representa a resistência relativa, \(R_{obs}\) é a resistência observada no corpo de prova e \(R_{ref}\) é a resistência de referência da classe do concreto.
Valores de `resistencia_relativa` **iguais a 1** indicam que a resistência observada corresponde à resistência de referência. Valores **maiores que 1** indicam resistência superior à referência, enquanto valores **menores que 1** indicam resistência inferior à referência.
A utilização dessa variável permite comparar o desempenho dos corpos de prova de diferentes classes em uma mesma escala relativa.
## Questão 22 — Classificação do desempenho
Para classificar os corpos de prova, foi utilizada a variável `resistencia_relativa`, criada na questão anterior. O critério adotado compara a resistência observada com a resistência de referência da classe do concreto.
Foram estabelecidas duas categorias:
* **"Abaixo da referência"**: `resistencia_relativa < 1`;
* **"Atingiu ou superou a referência"**: `resistencia_relativa >= 1`.
```{r}
# Classificação dos corpos de prova
dados_sem_na$classificacao <- ifelse(
dados_sem_na$resistencia_relativa < 1,
"Abaixo da referência",
"Atingiu ou superou a referência"
)
# Verificação das classificações
table(dados_sem_na$classificacao)
```
O critério foi escolhido por permitir uma interpretação direta do desempenho em relação à **resistência de referência da classe do concreto**. Quando a resistência relativa é menor que 1, o corpo de prova apresenta resistência inferior ao valor de referência. Quando é igual ou superior a 1, a resistência observada atinge ou supera esse valor.
Essa classificação fornece uma forma simples de avaliar o desempenho dos corpos de prova, sem estabelecer limites adicionais que não estejam diretamente relacionados à classe do concreto.
## Questão 23 — Desempenho acima da referência
Utilizando a variável `resistencia_relativa` criada na Questão 21, foi criada a variável `acima_media` para indicar se a resistência observada está acima da resistência de referência correspondente à classe do concreto.
```{r}
# Verificação da resistência em relação à referência da classe
dados_sem_na$acima_media <- dados_sem_na$resistencia_relativa > 1
# Visualização dos resultados
dados_sem_na[, c("tipo_concreto", "resistencia_mpa",
"resistencia_relativa", "acima_media")]
```
A variável assume **`TRUE`** quando a resistência observada é superior à resistência de referência da classe e **`FALSE`** quando é igual ou inferior a ela.
Assim, por exemplo, um corpo de prova de **C30** apresenta `TRUE` quando sua resistência é superior a **30 MPa**, pois sua `resistencia_relativa` será maior que 1.
## Questão 24 — Aplicação da função `split()`
A função `split()` foi utilizada para **dividir a base de dados em grupos de acordo com a variável `tipo_concreto`**. Dessa forma, cada classe de concreto é separada em um grupo independente, permitindo realizar análises específicas para cada tipo.
Para realizar a divisão, foi utilizada a base `dados_sem_na`, que contém apenas as observações completas após o tratamento dos dados.
```{r}
# Divisão da base por tipo de concreto
dados_por_tipo <- split(
dados_sem_na,
dados_sem_na$tipo_concreto
)
# Verificação dos grupos criados
names(dados_por_tipo)
# Contagem do número de observações em cada grupo
sapply(dados_por_tipo, nrow)
```
A função `split()` recebe a base de dados como primeiro argumento e a variável utilizada para definir os grupos como segundo argumento. Nesse caso, `tipo_concreto` determina a separação dos dados.
O resultado é armazenado no objeto `dados_por_tipo`, que passa a ser uma **lista contendo um grupo para cada classe de concreto**. Assim, os registros classificados como C25 ficam em um grupo, os registros C30 em outro, e assim sucessivamente.
A função `names()` permite verificar quais grupos foram criados, enquanto `sapply()` aplica a função `nrow()` a cada elemento da lista. Como `nrow()` retorna o número de linhas de uma base, o resultado corresponde ao **número de observações existentes em cada tipo de concreto**.
Para apresentar a quantidade de observações de forma mais organizada, pode-se utilizar:
```{r}
# Quantidade de observações por tipo de concreto
quantidade_por_tipo <- sapply(
dados_por_tipo,
nrow
)
quantidade_por_tipo
```
O resultado apresenta a quantidade de corpos de prova pertencentes a cada classe de concreto. Dessa forma, é possível verificar se os grupos **C25, C30, C35 e C40** possuem a mesma quantidade de observações ou se existe diferença no número de registros entre eles.
A utilização do `split()` é importante porque permite **organizar a base em subconjuntos independentes**, facilitando a aplicação posterior de outras funções do Base R. Essa estrutura será utilizada na **Questão 25**, na qual será calculada a resistência média de cada tipo de concreto utilizando a função `lapply()`.
Portanto, o `split()` não realiza nenhum cálculo estatístico por si só. Sua função principal nesta etapa é **separar os dados de acordo com uma variável categórica**, criando uma estrutura que facilita o processamento individual de cada grupo.
## Questão 25 — Aplicação da função `lapply()`
Utilizando a estrutura criada na questão anterior com a função `split()`, foi calculada a **resistência média à compressão de cada tipo de concreto**. Para isso, foi utilizada a função `lapply()`, que permite aplicar uma mesma função a cada grupo armazenado na lista `dados_por_tipo`.
```{r}
# Cálculo da resistência média de cada tipo de concreto
media_resistencia_tipo <- lapply(
dados_por_tipo,
function(x) mean(x$resistencia_mpa)
)
# Visualização dos resultados
media_resistencia_tipo
```
A função `lapply()` percorre cada elemento da lista `dados_por_tipo`. Em cada grupo, a expressão `x$resistencia_mpa` seleciona a variável de resistência e a função `mean()` calcula sua média.
O resultado é uma **lista**, na qual cada elemento corresponde a um tipo de concreto. Assim, são obtidas separadamente as resistências médias dos concretos **C25, C30, C35 e C40**.
Para visualizar os resultados de forma mais organizada, pode-se utilizar:
```{r}
# Apresentação das médias por tipo de concreto
data.frame(
tipo_concreto = names(media_resistencia_tipo),
resistencia_media_mpa = unlist(media_resistencia_tipo)
)
```
A tabela resultante permite comparar diretamente a resistência média das diferentes classes de concreto.
A utilização do `lapply()` é adequada porque a função aplica **a mesma operação a cada grupo**, evitando a necessidade de calcular manualmente a média de cada classe. Além disso, como os grupos foram previamente criados com `split()`, o código mantém uma sequência lógica: primeiro os dados são **separados por tipo de concreto** e, posteriormente, a resistência média é calculada **individualmente para cada grupo**.
Portanto, nesta questão, o `split()` foi responsável por **organizar a base em grupos**, enquanto o `lapply()` foi utilizado para **aplicar o cálculo da média de resistência a cada um desses grupos**. O resultado servirá de base para a Questão 26, na qual a mesma operação será realizada utilizando `sapply()`.
## Questão 26 — Aplicação da função `sapply()`
Nesta questão, a operação realizada anteriormente com `lapply()` foi repetida utilizando a função `sapply()`. O objetivo é calcular novamente a **resistência média de cada tipo de concreto**, utilizando a estrutura `dados_por_tipo` criada com `split()`.
```{r}
# Cálculo da resistência média de cada tipo de concreto
media_resistencia_tipo_sapply <- sapply(
dados_por_tipo,
function(x) mean(x$resistencia_mpa)
)
# Visualização dos resultados
media_resistencia_tipo_sapply
```
A função `sapply()` percorre cada grupo armazenado em `dados_por_tipo` e aplica a função `mean()` à variável `resistencia_mpa`. Dessa forma, são calculadas as médias de resistência para cada classe de concreto.
Para apresentar os resultados de forma organizada:
```{r}
# Organização dos resultados em tabela
data.frame(
tipo_concreto = names(media_resistencia_tipo_sapply),
resistencia_media_mpa = as.numeric(media_resistencia_tipo_sapply)
)
```
O resultado permite comparar diretamente a **resistência média dos concretos C25, C30, C35 e C40**.
**Diferença entre `lapply()` e `sapply()`:**
Embora as duas funções realizem a mesma operação neste caso, existe uma diferença importante na **estrutura do resultado produzido**.
A função `lapply()` **sempre retorna uma lista**, mantendo cada resultado como um elemento separado:
```{r}
# Resultado utilizando lapply()
media_resistencia_tipo_lapply <- lapply(
dados_por_tipo,
function(x) mean(x$resistencia_mpa)
)
media_resistencia_tipo_lapply
```
Já a função `sapply()` tenta **simplificar automaticamente o resultado**. Como neste caso cada grupo produz apenas um único valor numérico, os resultados podem ser organizados em um **vetor numérico nomeado**:
```{r}
# Resultado utilizando sapply()
media_resistencia_tipo_sapply
```
Assim, a diferença pode ser resumida da seguinte forma:
| Função | Resultado principal | Característica |
| ---------- | ------------------- | --------------------------------------------------------- |
| `lapply()` | Lista | Mantém os resultados separados em uma lista |
| `sapply()` | Vetor | Tenta simplificar a lista para uma estrutura mais simples |
Portanto, **os valores calculados são os mesmos**, mas a forma como o R apresenta e armazena os resultados é diferente. O `lapply()` é mais apropriado quando se deseja **preservar uma estrutura de lista**, enquanto o `sapply()` é mais conveniente quando os resultados podem ser simplificados para um vetor ou matriz.
Neste caso específico, como cada tipo de concreto gera apenas **uma resistência média**, o `sapply()` produz um resultado mais compacto e fácil de visualizar. Já o `lapply()` mantém explicitamente a estrutura de lista criada a partir dos grupos.
Dessa forma, ambas as funções são adequadas para o cálculo solicitado, mas o `sapply()` oferece uma apresentação mais simples dos resultados quando todos os grupos retornam um único valor.
## Questão 27 — Aplicação da função `apply()` para médias
Para calcular a média das principais propriedades do concreto, foram selecionadas as variáveis quantitativas `resistencia_mpa`, `cimento_kg_m3`, `relacao_a_c`, `abatimento_mm`, `densidade_kg_m3` e `absorção_agregado_pct`. Em seguida, foi utilizada a função `apply()` para calcular a média de cada variável.
```{r}
# Seleção das variáveis quantitativas relacionadas às propriedades do concreto
propriedades_concreto <- dados_sem_na[, c(
"resistencia_mpa",
"cimento_kg_m3",
"relacao_a_c",
"abatimento_mm",
"densidade_kg_m3",
"absorção_agregado_pct"
)]
# Cálculo da média de cada variável
apply(propriedades_concreto, 2, mean)
```
A função `apply()` foi aplicada sobre as colunas da base, utilizando o argumento `2`, que indica que a função `mean()` deve ser aplicada **a cada coluna**.
Dessa forma, o resultado apresenta a **média de cada propriedade quantitativa selecionada**, permitindo obter uma caracterização geral dos concretos analisados.
## Questão 28 — Aplicação da função `apply()` por observação
Nesta etapa, foi utilizada a função `apply()` para calcular, para cada corpo de prova, a **média das variáveis quantitativas relacionadas às propriedades do concreto**.
```{r}
# Cálculo da média das propriedades para cada observação
media_observacao <- apply(
propriedades_concreto,
1,
mean
)
# Visualização dos resultados
media_observacao
```
O argumento `1` indica que a função deve ser aplicada **por linha**, ou seja, para cada observação. Assim, `mean()` calcula uma média envolvendo as seis variáveis quantitativas selecionadas.
Entretanto, essa medida **não possui necessariamente uma interpretação física direta**. Isso ocorre porque as variáveis utilizadas possuem **unidades e significados diferentes**, como MPa, kg/m³, mm, porcentagem e uma razão adimensional.
Portanto, embora a média possa ser calculada matematicamente, seu resultado não representa diretamente uma propriedade física do concreto. Nesse caso, a medida deve ser entendida apenas como um **resumo numérico das variáveis selecionadas**, e não como uma grandeza física com significado técnico específico.
## Questão 29 — Aplicação de `for` e `if`
Nesta etapa, foi utilizada uma estrutura de repetição `for` em conjunto com a estrutura condicional `if` para percorrer as observações da base e identificar os corpos de prova cuja resistência à compressão está **acima da resistência média de sua respectiva classe de concreto**.
Para cada observação, a classe do concreto é identificada e sua resistência individual é comparada com a resistência média correspondente àquela classe.
```{r}
# Cálculo da resistência média de cada tipo de concreto
media_tipo <- aggregate(
resistencia_mpa ~ tipo_concreto,
data = dados_sem_na,
FUN = mean
)
# Vetor vazio para armazenar os corpos de prova
# que apresentam resistência acima da média de sua classe
acima_da_media <- character(0)
# Percorrendo todas as observações da base
for (i in 1:nrow(dados_sem_na)) {
# Identificação do tipo de concreto da observação
tipo <- dados_sem_na$tipo_concreto[i]
# Localização da resistência média do respectivo tipo
media <- media_tipo$resistencia_mpa[
media_tipo$tipo_concreto == tipo
]
# Comparação da resistência do corpo de prova com a média
if (dados_sem_na$resistencia_mpa[i] > media) {
# Armazenamento do identificador do corpo de prova
acima_da_media <- c(
acima_da_media,
dados_sem_na$id_corpo_prova[i]
)
}
}
# Identificação dos registros completos
# que apresentam resistência acima da média de sua classe
resultado_q29 <- dados_sem_na[
dados_sem_na$id_corpo_prova %in% acima_da_media,
]
# Apresentação dos resultados
resultado_q29
# Quantidade de corpos de prova acima da média
length(acima_da_media)
# Lista dos identificadores dos corpos de prova
acima_da_media
```
O código calcula inicialmente a **resistência média de cada tipo de concreto** utilizando `aggregate()`. Em seguida, o `for` percorre todas as observações presentes em `dados_sem_na`.
Para cada corpo de prova, o código identifica seu `tipo_concreto` e localiza a resistência média correspondente. A estrutura `if` compara a resistência individual com essa média. Quando a resistência observada é maior que a média de sua respectiva classe, o identificador do corpo de prova é armazenado no vetor `acima_da_media`.
A condição utilizada foi:
```{r}
dados_sem_na$resistencia_mpa[i] > media
```
Portanto, somente os corpos de prova que apresentam resistência **estritamente superior à média de sua própria classe** são selecionados.
O objeto `resultado_q29` apresenta os **registros completos dos corpos de prova identificados**, enquanto `length(acima_da_media)` informa a quantidade total de observações que apresentam resistência acima da média de sua respectiva classe.
## Questão 30 — Abordagem vetorizada
A questão anterior foi repetida utilizando uma **abordagem vetorizada**, sem `for` e `if`. A comparação é realizada simultaneamente para todas as observações.
```{r}
# Resistência média por tipo de concreto
media_tipo <- aggregate(
resistencia_mpa ~ tipo_concreto,
data = dados_sem_na,
FUN = mean
)
# Média correspondente a cada observação
media_por_observacao <- media_tipo$resistencia_mpa[
match(dados_sem_na$tipo_concreto,
media_tipo$tipo_concreto)
]
# Comparação vetorizada
acima_da_media_vetor <-
dados_sem_na$resistencia_mpa > media_por_observacao
# Corpos de prova acima da média
resultado_q30 <- dados_sem_na[acima_da_media_vetor, ]
resultado_q30
```
A abordagem vetorizada é **mais simples, mais legível e geralmente mais eficiente** que a solução com `for` e `if`, pois realiza a comparação de todas as observações simultaneamente.
A solução com `for` e `if` é útil para demonstrar estruturas de repetição e decisão, enquanto a abordagem vetorizada é mais adequada para o processamento de dados no R.
**Conclusão:** para esta análise, considero a **abordagem vetorizada a melhor solução**, por utilizar menos código e realizar o processamento de forma mais direta.
## Questão 31 — Comparação entre blocos
Para verificar descritivamente a afirmação de que os concretos utilizados no **Bloco C apresentam desempenho superior** aos demais blocos, foi calculada a resistência média à compressão para cada obra. Também foi comparada a média do Bloco C com a média conjunta dos demais blocos.
```{r}
# Resistência média por bloco
media_obra <- aggregate(
resistencia_mpa ~ obra,
data = dados_sem_na,
FUN = mean
)
# Média do Bloco C
media_bloco_c <- mean(
dados_sem_na$resistencia_mpa[dados_sem_na$obra == "Bloco C"]
)
# Média dos demais blocos
media_demais <- mean(
dados_sem_na$resistencia_mpa[dados_sem_na$obra != "Bloco C"]
)
# Resultados
media_obra
media_bloco_c
media_demais
```
A análise descritiva apresentou as seguintes resistências médias:
| Bloco | Resistência média (MPa) |
| ----------- | ----------------------: |
| Bloco A | 33,43 |
| Bloco B | 35,68 |
| **Bloco C** | **32,62** |
| Bloco D | 33,35 |
A resistência média do **Bloco C foi de aproximadamente 32,62 MPa**, enquanto a média conjunta dos demais blocos foi de aproximadamente **34,31 MPa**.
Portanto, **os dados não dão suporte, em termos descritivos, à afirmação do engenheiro**. O Bloco C apresentou a menor resistência média entre os quatro blocos analisados, ficando abaixo dos blocos A, B e D.
Essa conclusão é exclusivamente **descritiva**, baseada na comparação das médias observadas, não sendo possível afirmar, a partir dessa análise, se as diferenças são estatisticamente significativas. Além disso, fatores como **classe do concreto e idade dos corpos de prova** podem influenciar as diferenças observadas entre os blocos.
## Questão 32 — Consumo de cimento e resistência
Para investigar a afirmação de que **“quanto maior o consumo de cimento, maior tende a ser a resistência do concreto”**, devem ser analisadas conjuntamente as variáveis `cimento_kg_m3` e `resistencia_mpa`.
```{r}
# Análise conjunta entre consumo de cimento e resistência
dados_sem_na[, c("cimento_kg_m3", "resistencia_mpa")]
```
A variável `cimento_kg_m3` representa o **consumo de cimento por metro cúbico de concreto**, enquanto `resistencia_mpa` representa a **resistência à compressão** dos corpos de prova.
Para uma análise mais adequada, também é importante considerar `relacao_a_c`, `tipo_concreto` e `idade_dias`, pois essas variáveis podem influenciar a resistência e interferir na relação observada entre consumo de cimento e resistência.
Portanto, as principais variáveis a serem analisadas conjuntamente são **`cimento_kg_m3` e `resistencia_mpa`**, considerando também **`relacao_a_c`, `tipo_concreto` e `idade_dias`** como variáveis de contexto.
## Questão 33 — Relação água/cimento e resistência
Para investigar a relação entre a relação água/cimento e a resistência à compressão, foi calculada a correlação entre as duas variáveis.
```{r}
cor(
dados_sem_na$relacao_a_c,
dados_sem_na$resistencia_mpa
)
```
A correlação obtida foi **negativa (aproximadamente -0,76)**, indicando que, na base analisada, **maiores relações água/cimento tendem a estar associadas a menores resistências**.
Esse padrão merece investigação e está de acordo com o comportamento esperado do concreto. Entretanto, a resistência também pode ser influenciada por fatores como **tipo de concreto, consumo de cimento e idade**.
## Questão 34 — Evolução da resistência com a idade
Para comparar a resistência média dos corpos de prova em diferentes idades, foi utilizada a função `aggregate()`.
```{r}
# Resistência média por idade
media_idade <- aggregate(
resistencia_mpa ~ idade_dias,
data = dados_sem_na,
FUN = mean
)
# Ordenação das idades
media_idade <- media_idade[
order(media_idade$idade_dias),
]
media_idade
```
Os resultados indicam uma **tendência geral de aumento da resistência com o avanço da idade**. Entretanto, essa evolução não é perfeitamente crescente: em algumas idades, a resistência média apresenta pequenas reduções em relação à idade anterior. Essas variações podem ocorrer devido à **variabilidade dos corpos de prova, condições de cura e diferenças entre os concretos analisados**.
Portanto, a tendência geral é de **aumento da resistência com a idade**, mas com algumas oscilações nos valores médios observados.
## Questão 35 — Informações estatísticas relevantes
Para o relatório técnico, as cinco informações mais importantes são:
1. **Resistência média à compressão (MPa):** indica o desempenho médio dos concretos.
2. **Resistência mínima e máxima:** permite identificar a amplitude dos resultados e possíveis valores extremos.
3. **Resistência média por classe de concreto:** possibilita comparar o desempenho entre C25, C30, C35 e C40.
4. **Resistência média por idade:** permite acompanhar a evolução da resistência ao longo do tempo.
5. **Relação água/cimento e resistência:** permite avaliar uma das principais relações que influenciam o desempenho mecânico do concreto.
Essas informações fornecem uma visão geral do **desempenho, variabilidade e evolução da resistência**, auxiliando o engenheiro na tomada de decisões relacionadas ao controle tecnológico.
## 🏆 Desafio Final
Nesta etapa final, foi desenvolvido um **script integrado em R** para simular a atuação de um engenheiro responsável pelo controle e tratamento de uma base de dados produzida por diferentes profissionais. Como os erros não são conhecidos previamente, o código foi organizado para realizar uma sequência de **inspeção, diagnóstico, limpeza, tratamento e análise dos dados**.
O objetivo é transformar a base inicialmente bruta em uma estrutura mais confiável para a realização de análises estatísticas e para a **tomada de decisão na Engenharia Civil**.
### Script final
O código abaixo reúne as principais etapas desenvolvidas ao longo da atividade, utilizando funções do **Base R** trabalhadas em aula.
```r
# ------------------------------------------------------------
# 1. IMPORTAÇÃO DA BASE
# ------------------------------------------------------------
dados <- read.csv("base_de_dados.csv",
header = TRUE,
sep = ";")
# Visualização inicial
head(dados)
# ------------------------------------------------------------
# 2. INSPEÇÃO INICIAL
# ------------------------------------------------------------
# Dimensões da base
dim(dados)
# Estrutura das variáveis
str(dados)
# Resumo estatístico
summary(dados)
# Tipos das variáveis
sapply(dados, class)
# ------------------------------------------------------------
# 3. IDENTIFICAÇÃO DE VALORES AUSENTES
# ------------------------------------------------------------
ausentes <- c("", " ", "NA", "N/A", "-", "null", "NULL")
# Quantidade de valores ausentes por variável
sapply(dados, function(x)
sum(is.na(x) | x %in% ausentes, na.rm = TRUE)
)
# Localização das observações com valores ausentes
which(apply(dados, 1, function(x)
any(is.na(x) | x %in% ausentes)
))
# ------------------------------------------------------------
# 4. IDENTIFICAÇÃO DE INCONSISTÊNCIAS
# ------------------------------------------------------------
# Categorias existentes em obra
unique(dados$obra)
# Categorias existentes em tipo_concreto
unique(dados$tipo_concreto)
# Verificação de espaços desnecessários
sapply(dados, function(x)
sum(grepl("^ | $", x))
)
# Verificação de vírgulas decimais
sapply(dados, function(x)
sum(grepl(",", x))
)
# ------------------------------------------------------------
# 5. VERIFICAÇÃO DE VALORES SUSPEITOS
# ------------------------------------------------------------
# Idade dos corpos de prova
dados[dados$idade_dias <= 0 |
dados$idade_dias > 56, ]
# Resistência
dados[dados$resistencia_mpa < 20 |
dados$resistencia_mpa > 60, ]
# Abatimento
dados[dados$abatimento_mm < 10 |
dados$abatimento_mm > 220, ]
# Densidade
dados[dados$densidade_kg_m3 < 2000 |
dados$densidade_kg_m3 > 2600, ]
# Relação água/cimento
dados[dados$relacao_a_c < 0.40 |
dados$relacao_a_c > 0.70, ]
# Absorção
dados[dados$`absorção_agregado_pct` < 0 |
dados$`absorção_agregado_pct` > 10, ]
# ------------------------------------------------------------
# 6. CRIAÇÃO DA BASE PARA LIMPEZA
# ------------------------------------------------------------
dados_limpos <- dados
# ------------------------------------------------------------
# 7. CORREÇÃO DAS VARIÁVEIS QUALITATIVAS
# ------------------------------------------------------------
# Remoção de espaços desnecessários
dados_limpos$obra <- trimws(dados_limpos$obra)
# Padronização das classes de concreto
dados_limpos$tipo_concreto <-
toupper(trimws(dados_limpos$tipo_concreto))
# ------------------------------------------------------------
# 8. CORREÇÃO DAS VARIÁVEIS QUANTITATIVAS
# ------------------------------------------------------------
dados_limpos$idade_dias <-
as.numeric(dados_limpos$idade_dias)
dados_limpos$resistencia_mpa <-
as.numeric(
gsub(",",
".",
gsub("O",
"0",
dados_limpos$resistencia_mpa))
)
dados_limpos$cimento_kg_m3 <-
as.numeric(
gsub("O",
"0",
dados_limpos$cimento_kg_m3)
)
dados_limpos$relacao_a_c <-
as.numeric(
gsub(",",
".",
dados_limpos$relacao_a_c)
)
dados_limpos$abatimento_mm <-
as.numeric(dados_limpos$abatimento_mm)
dados_limpos$densidade_kg_m3 <-
as.numeric(dados_limpos$densidade_kg_m3)
dados_limpos$`absorção_agregado_pct` <-
as.numeric(dados_limpos$`absorção_agregado_pct`)
# ------------------------------------------------------------
# 9. VERIFICAÇÃO DA BASE APÓS A LIMPEZA
# ------------------------------------------------------------
str(dados_limpos)
summary(dados_limpos)
# Verificação dos tipos
sapply(dados_limpos, class)
# ------------------------------------------------------------
# 10. TRATAMENTO DOS VALORES AUSENTES
# ------------------------------------------------------------
# Criação da base final somente com observações completas
dados_finais <-
dados_limpos[complete.cases(dados_limpos), ]
# Número de observações após o tratamento
nrow(dados_finais)
# ------------------------------------------------------------
# 11. ESTATÍSTICAS DESCRITIVAS
# ------------------------------------------------------------
# Resistência média global
media_global <-
mean(dados_finais$resistencia_mpa)
media_global
# Resistência mínima
min(dados_finais$resistencia_mpa)
# Resistência máxima
max(dados_finais$resistencia_mpa)
# Resistência média por obra
media_obra <-
aggregate(resistencia_mpa ~ obra,
data = dados_finais,
FUN = mean)
media_obra
# Resistência média por tipo de concreto
media_tipo <-
aggregate(resistencia_mpa ~ tipo_concreto,
data = dados_finais,
FUN = mean)
media_tipo
# Resistência média por idade
media_idade <-
aggregate(resistencia_mpa ~ idade_dias,
data = dados_finais,
FUN = mean)
media_idade
# ------------------------------------------------------------
# 12. ANÁLISE DAS PROPRIEDADES DO CONCRETO
# ------------------------------------------------------------
aggregate(
cbind(resistencia_mpa,
cimento_kg_m3,
relacao_a_c,
abatimento_mm,
densidade_kg_m3) ~ tipo_concreto,
data = dados_finais,
FUN = mean
)
# ------------------------------------------------------------
# 13. PRIMEIRA VARIÁVEL DERIVADA:
# RESISTÊNCIA RELATIVA
# ------------------------------------------------------------
resistencia_referencia <-
ifelse(dados_finais$tipo_concreto == "C25", 25,
ifelse(dados_finais$tipo_concreto == "C30", 30,
ifelse(dados_finais$tipo_concreto == "C35", 35,
ifelse(dados_finais$tipo_concreto == "C40", 40,
NA))))
dados_finais$resistencia_relativa <-
dados_finais$resistencia_mpa /
resistencia_referencia
# Visualização
dados_finais[, c("tipo_concreto",
"resistencia_mpa",
"resistencia_relativa")]
# ------------------------------------------------------------
# 14. SEGUNDA VARIÁVEL DERIVADA:
# CLASSIFICAÇÃO DO DESEMPENHO
# ------------------------------------------------------------
dados_finais$classificacao <-
ifelse(
dados_finais$resistencia_relativa >= 1,
"Atingiu ou superou a referência",
"Abaixo da referência"
)
table(dados_finais$classificacao)
# ------------------------------------------------------------
# 15. TERCEIRA VARIÁVEL DERIVADA:
# DESEMPENHO ACIMA DA MÉDIA DA CLASSE
# ------------------------------------------------------------
media_tipo_2 <-
aggregate(resistencia_mpa ~ tipo_concreto,
data = dados_finais,
FUN = mean)
media_por_observacao <-
media_tipo_2$resistencia_mpa[
match(dados_finais$tipo_concreto,
media_tipo_2$tipo_concreto)
]
dados_finais$acima_media <-
dados_finais$resistencia_mpa >
media_por_observacao
table(dados_finais$acima_media)
# ------------------------------------------------------------
# 16. UTILIZAÇÃO DE split() E sapply()
# ------------------------------------------------------------
dados_por_tipo <-
split(dados_finais,
dados_finais$tipo_concreto)
# Quantidade de observações por classe
quantidade_por_tipo <-
sapply(dados_por_tipo, nrow)
quantidade_por_tipo
# Resistência média por classe
media_resistencia_tipo <-
sapply(
dados_por_tipo,
function(x)
mean(x$resistencia_mpa)
)
media_resistencia_tipo
# ------------------------------------------------------------
# 17. APLICAÇÃO DE apply()
# ------------------------------------------------------------
propriedades <-
dados_finais[, c(
"resistencia_mpa",
"cimento_kg_m3",
"relacao_a_c",
"abatimento_mm",
"densidade_kg_m3"
)]
# Média das propriedades
apply(propriedades, 2, mean)
# ------------------------------------------------------------
# 18. RELAÇÃO ÁGUA/CIMENTO E RESISTÊNCIA
# ------------------------------------------------------------
cor(
dados_finais$relacao_a_c,
dados_finais$resistencia_mpa
)
# ------------------------------------------------------------
# 19. COMPARAÇÃO ENTRE BLOCOS
# ------------------------------------------------------------
media_obra
# Maior média
media_obra[
which.max(media_obra$resistencia_mpa),
]
# Menor média
media_obra[
which.min(media_obra$resistencia_mpa),
]
# --------------------------------------------------------------
# INFORMAÇÕES PARA AUXILIAR NO PROCESSO DECISSÓRIO DO ENGENHEIRO
# --------------------------------------------------------------
cat("RELATÓRIO RESUMIDO DO CONTROLE\n")
cat("Número de observações analisadas:",
nrow(dados_finais), "\n")
cat("Resistência média global:",
round(media_global, 2), "MPa\n")
cat("Menor resistência:",
min(dados_finais$resistencia_mpa),
"MPa\n")
cat("Maior resistência:",
max(dados_finais$resistencia_mpa),
"MPa\n")
cat("Bloco com maior resistência média:",
as.character(
media_obra$obra[
which.max(media_obra$resistencia_mpa)
]
), "\n")
cat("Resistência média do melhor bloco:",
round(
max(media_obra$resistencia_mpa),
2
),
"MPa\n")
```
O script realiza o processamento de forma sequencial. Inicialmente, a base é importada e inspecionada para verificar suas **dimensões, estrutura, tipos de variáveis e estatísticas descritivas**. Em seguida, são procurados valores ausentes, erros de preenchimento, categorias despadronizadas e valores potencialmente incompatíveis com o contexto do concreto.
Na etapa de limpeza, a base original é preservada no objeto `dados`, enquanto uma cópia chamada `dados_limpos` é utilizada para as correções. As variáveis qualitativas são padronizadas com `trimws()` e `toupper()`, enquanto as variáveis quantitativas são corrigidas e convertidas para o formato numérico.
Após o tratamento, foi criada a base `dados_finais`, contendo apenas as observações completas. Essa base é utilizada nas análises estatísticas posteriores, evitando que valores ausentes interfiram nos cálculos.
Foram também criadas variáveis derivadas para ampliar a interpretação dos dados. A variável `resistencia_relativa` compara a resistência observada com a resistência de referência da classe do concreto. A variável `classificacao` indica se o corpo de prova atingiu ou superou essa referência. Além disso, `acima_media` identifica os corpos de prova cuja resistência está acima da média de sua respectiva classe.
As funções `aggregate()`, `split()`, `sapply()` e `apply()` foram utilizadas para produzir informações agrupadas e estatísticas relevantes para a análise do desempenho dos concretos.
### Informações geradas para o engenheiro
A partir do script, podem ser obtidas informações importantes para o acompanhamento do controle tecnológico, como:
* **número de corpos de prova analisados** após o tratamento;
* **resistência média global**;
* **menor resistência observada**;
* **maior resistência observada**;
* **resistência média por bloco**;
* **resistência média por classe de concreto**;
* **resistência média por idade**;
* **quantidade de corpos de prova por classe**;
* **relação entre água/cimento e resistência**;
* **quantidade de corpos de prova acima da média de sua classe**;
* **quantidade de corpos de prova que atingiram ou superaram a resistência de referência**.
Essas informações permitem ao engenheiro identificar diferenças de desempenho entre os blocos, acompanhar a evolução da resistência e verificar possíveis situações que mereçam investigação adicional.
### Principal problema identificado
O principal problema encontrado na base foi a presença de **inconsistências de preenchimento nas variáveis quantitativas**. Alguns valores que deveriam ser numéricos foram armazenados como texto devido à utilização de vírgulas como separador decimal e à presença da letra `O` no lugar do número `0`.
Um exemplo foi o registro `3O,4`, que representa um provável erro de digitação. Como a coluna contém esse tipo de caractere, o R passa a interpretar a variável inteira como `character`, mesmo que a maioria dos valores seja numérica.
Também foram identificadas inconsistências nas variáveis qualitativas, como `Bloco B `, contendo espaço adicional, e `c30`, escrito com letra minúscula.
A decisão adotada foi **corrigir os erros de formatação e padronização identificados**, converter as variáveis quantitativas para o formato numérico e remover as observações que permaneceram incompletas após o tratamento. A base original foi preservada para garantir a rastreabilidade das alterações realizadas.
# 🧠 Considerações finais
O processamento e a limpeza dos dados são etapas fundamentais antes da aplicação de métodos estatísticos na Engenharia Civil porque **resultados estatísticos confiáveis dependem diretamente da qualidade dos dados utilizados**. Erros de digitação, valores ausentes, categorias diferentes para uma mesma informação e variáveis classificadas incorretamente podem alterar médias, correlações e comparações, levando a conclusões técnicas equivocadas.
No caso analisado, um dos principais problemas foi a presença de **valores quantitativos registrados como texto**, principalmente devido a erros de digitação e separadores decimais inconsistentes. Esse problema alterou a forma como o R interpretou algumas variáveis e precisou ser corrigido antes da realização das análises.
A limpeza permitiu transformar a base bruta em uma estrutura mais organizada e adequada ao processamento estatístico. Dessa forma, as informações obtidas passam a oferecer maior suporte para decisões relacionadas ao **controle tecnológico, desempenho dos concretos e acompanhamento da qualidade da obra**.
O principal aprendizado do desafio é que o trabalho do engenheiro não consiste apenas em calcular estatísticas, mas também em **verificar a qualidade dos dados antes de utilizá-los para tomar decisões**. Portanto, a combinação entre conhecimento técnico da Engenharia Civil e domínio das ferramentas de análise de dados é fundamental para produzir informações confiáveis e úteis para a gestão das obras.
# 📖 Referências
::: {#refs}