Autor

Otávio Neiva e Gregório Grazziotti

Data de Publicação

07/09/2026, 18:00

1 📌 Introdução

A garantia da segurança estrutural, do desempenho mecânico e da durabilidade do concreto armado em obras de infraestrutura e edificações depende da rigidez metodológica aplicada ao controle tecnológico dos materiais cimentícios (Associação Brasileira de Normas Técnicas, 2015a, 2023). A verificação sistemática da consistência no estado fresco pelo ensaio de abatimento do tronco de cone (Slump Test) (Associação Brasileira de Normas Técnicas, 2020) e da resistência à compressão axial (\(f_c\)) no estado endurecido aos 7, 14, 28 e 56 dias (Associação Brasileira de Normas Técnicas, 2015b, 2018) constitui a base normativa para a comprovação da conformidade das misturas em relação à resistência característica de projeto (\(f_{ck}\)) (Associação Brasileira de Normas Técnicas, 2015c).

Entretanto, nos canteiros de obra, a coleta descentralizada de dados operacionais conduzida por múltiplos profissionais frequentemente introduz um ruído amostral significativo (Mehta e Monteiro, 2014). Inconsistências como valores ausentes (\(NA\)), desvios categóricos em strings, incorreções de escala decimal e a inserção involuntária de caracteres alfanuméricos em campos quantitativos corrompem as variáveis do banco de dados. Em um ambiente computacional estritamente tipado como a linguagem R (R Core Team, 2024), a presença de um único caractere indevido em uma coluna quantitativa desencadeia a coerção implícita para o tipo character, impossibilitando o cálculo direto de métricas estatísticas essenciais para a tomada de decisão técnica (Wickham et al., 2019; Wickham e Grolemund, 2017).

Para superar esses gargalos, este relatório aborda a aplicação de uma rotina moderna e integrada de Ciência de Dados orientada à Engenharia Civil. Utilizam-se prioritariamente as ferramentas da família tidyverse — integrando os pacotes readr (leitura e parsing), dplyr (manipulação funcional), tidyr (organização de dados), stringr (tratamento de texto), purrr (programação funcional) e ggplot2 (visualização gráfica) (Wickham et al., 2019) — combinadas ao operador pipe nativo (|>).

A análise abrange uma amostragem de 100 corpos de prova e 10 variáveis de controle tecnológico, articulando o diagnóstico e a higienização dos dados às leis físico-químicas da tecnologia do concreto, como a Lei de Abrams (Abrams, 1918; Neville, 2016).

2 🎯 Objetivos

2.1 Objetivo Geral

Desenvolver e aplicar uma rotina automatizada e reprodutível de inspeção, diagnóstico, higienização, transformação e exploração de dados do controle tecnológico do concreto, utilizando prioritariamente os pacotes da família tidyverse (readr, dplyr, tidyr, stringr, purrr e ggplot2) (Wickham et al., 2019) e o operador pipe nativo (|>), visando transformar registros operacionais brutos provenientes de canteiros de obra em informações estruturadas e confiáveis para o suporte à tomada de decisão na Engenharia Civil.

2.2 Objetivos Específicos

  • Inspecionar a estrutura e a qualidade da base bruta: Carregar o registro primário com read_csv2(), avaliar a tipagem e dimensão da matriz amostral via glimpse() e mapear sistematicamente a ocorrência de valores ausentes (\(NA\)) utilizando across().

  • Implementar rotinas automatizadas de limpeza e padronização: Corrigir erros de digitação, substituir caracteres indevidos, remover espaços adicionais e padronizar categorias com funções do pacote stringr (str_trim(), str_to_upper(), str_replace_all()), convertendo colunas quantitativas coagidas com parse_double().

  • Corrigir anomalias e desvios de escala: Identificar e realinhar erros de ordem de grandeza e deslocamento decimal em variáveis reológicas e físico-mecânicas (idade, consumo de cimento, abatimento, densidade e absorção) com if_else().

  • Executar imputação condicional estocástica de dados faltantes: Preencher registros ausentes (\(NA\)) com base nas médias amostrais de cada traço nominal (tipo_concreto) via group_by() + mutate(), preservando a esperança matemática intra-classe \(\mathbb{E}[X | G_k]\) e a potência estatística da amostragem sem descartar observações (Little e Rubin, 2019).

  • Desenvolver variáveis derivadas de conformidade estrutural: Criar indicadores adimensionais de Resistência Relativa (\(R_{rel} = f_{c,obs} / f_{ck}\)) e classificação booleana de aceitação normatizada perante a ABNT NBR 12655 (Associação Brasileira de Normas Técnicas, 2015a) e ABNT NBR 6118 (Associação Brasileira de Normas Técnicas, 2023) empregando mutate() e case_when().

  • Analisar o comportamento físico-mecânico e reológico: Agrupar e sumarizar variáveis quantitativas com group_by(), summarise() e across(), correlacionando o consumo de cimento e o fator água/cimento (\(\text{a/c}\)) com os preceitos teóricos da Lei de Abrams (Abrams, 1918; Neville, 2016) e produzindo visualizações gráficas de alto desempenho com ggplot2.


3 📚 Fundamentação Teórica

A análise e o processamento de dados do controle tecnológico do concreto exigem um duplo embasamento: o rigor das diretrizes normativas e leis físico-químicas da Engenharia Civil, combinado aos princípios modernos de Ciência de Dados e programação funcional do ecossistema tidyverse (R Core Team, 2024; Wickham et al., 2019; Wickham e Grolemund, 2017).


3.1 Normatização e Controle Tecnológico do Concreto (ABNT)

O controle de qualidade e recebimento do concreto no Brasil é regulamentado por um conjunto de normas técnicas da Associação Brasileira de Normas Técnicas (ABNT):

  • ABNT NBR 8953: Classifica os concretos para fins estruturais em grupos de resistência (Associação Brasileira de Normas Técnicas, 2015c). As classes analisadas neste estudo (\(C25, C30, C35, C40\)) pertencem ao Grupo I (concretos de resistência normal), em que o número nominal representa a resistência característica à compressão (\(f_{ck}\)) especificada em megapascals (\(\text{MPa}\)) aos 28 dias de cura.
  • ABNT NBR 12655: Estabelece os procedimentos de preparo, controle, recebimento e aceitação do concreto (Associação Brasileira de Normas Técnicas, 2015a). Define os critérios de amostragem e ensaios para verificação da conformidade dos lotes de concretagem.
  • ABNT NBR 5738 e NBR 5739: Padronizam, respectivamente, a moldagem e cura de corpos de prova cilíndricos e o ensaio de compressão axial para determinação da resistência mecânica (\(f_c\)) (Associação Brasileira de Normas Técnicas, 2015b, 2018).
  • ABNT NBR 16889: Regulamenta o ensaio de abatimento do tronco de cone (Slump Test) para avaliação da consistência e trabalhabilidade do concreto no estado fresco (Associação Brasileira de Normas Técnicas, 2020).
  • ABNT NBR 6118: Fixa os requisitos básicos para o projeto de estruturas de concreto e prescreve os parâmetros de amadurecimento mecânico e durabilidade da estrutura (Associação Brasileira de Normas Técnicas, 2023).

3.2 Leis Físico-Químicas da Tecnologia do Concreto

3.2.1 Lei de Abrams e Relação Água/Cimento (\(\text{a/c}\))

Formulada por Duff Abrams (Abrams, 1918), a lei fundamental da tecnologia do concreto estabelece que a resistência à compressão de uma mistura totalmente adensada é inversamente proporcional à razão entre o volume de água livre e o volume de cimento (Mehta e Monteiro, 2014; Neville, 2016):

\[f_c = \frac{A}{B^{(\text{a/c})}}\]

Onde \(f_c\) representa a resistência à compressão axial (\(\text{MPa}\)), \(\text{a/c}\) é a relação água/cimento em massa (\(\text{kg/kg}\)) e \(A, B\) são constantes empíricas características dos materiais constituintes e das condições de ensaio. A redução do fator \(\text{a/c}\) diminui a porosidade capilar da pasta endurecida e eleva a resistência mecânica final.

3.2.2 Consumo de Cimento (\(C\)) e Densidade Aparente (\(\rho\))

O consumo de cimento por metro cúbico (\(C\), em \(\text{kg/m}^3\)) relaciona-se com a densidade aparente do concreto fresco (\(\rho\), em \(\text{kg/m}^3\)) e com a proporção dos materiais no traço em massa (\(1 : m : \text{a/c}\)) (Helene e Terzian, 1992):

\[C = \frac{\rho}{1 + m + \text{a/c}}\]

Onde \(m\) representa a proporção total de agregados secos (miúdo + graúdo) em relação à massa de cimento.

3.2.3 Critério de Conformidade e Aceitação Estrutural

Para a verificação individual e loteada de cada corpo de prova perante a especificação de projeto (\(f_{ck}\)), define-se o indicador adimensional de Resistência Relativa (\(R_{rel}\)) (Associação Brasileira de Normas Técnicas, 2015a, 2023):

\[R_{rel} = \frac{f_{c,obs}}{f_{ck}}\]

\[\text{Classificação} = \begin{cases} \text{"Conforme"}, & \text{se } R_{rel} \ge 1{,}0 \\ \text{"Não Conforme"}, & \text{se } R_{rel} < 1{,}0 \end{cases}\]


3.3 Ciência de Dados e o Ecossistema Tidyverse

3.3.1 A Filosofia Tidy Data e o Operador Pipe (|>)

A família tidyverse fundamenta-se no conceito de Tidy Data (dados organizados), em que cada variável corresponde a uma coluna, cada observação corresponde a uma linha e cada tipo de unidade observacional forma uma tabela (Wickham e Grolemund, 2017). O uso do operador pipe nativo da linguagem R (|>) permite a construção de fluxos de transformação encadeados e legíveis:

\[\text{dados} \mid> \text{função}_1() \mid> \text{função}_2() \mid> \text{função}_3()\]

3.3.2 As Ferramentas do Tidyverse Aplicadas ao Tratamento de Dados

  • readr (read_csv2, parse_double): Leitura eficiente de arquivos delimitados e conversão estrita de tipos numéricos com tratamento do separador decimal (Wickham et al., 2019).
  • stringr (str_trim, str_to_upper, str_replace_all, str_detect): Manipulação padronizada de strings e expressões regulares para correção de ruídos, espaços ocultos e erros de digitação.
  • dplyr (filter, select, mutate, summarise, group_by, across, case_when, if_else): Gramática de manipulação de dados para filtragem, criação de variáveis e agregação estatística em grupo.
  • tidyr (pivot_longer, pivot_wider, drop_na, replace_na): Reestruturação geométrica da base e tratamento de dados ausentes.
  • purrr (map, map_dbl): Programação funcional avançada e aplicação de funções sem a necessidade de laços iterativos interpretados (Wickham et al., 2019).
  • ggplot2 (geom_boxplot, geom_point, geom_smooth): Construção de gráficos estatísticos com base na Gramática dos Gráficos (Wickham e Grolemund, 2017).

3.3.3 Imputação Estocástica de Dados Ausentes (\(NA\))

A eliminação simples de observações com dados faltantes (listwise deletion) reduz a potência dos testes estatísticos e introduz viés amostral (Little e Rubin, 2019). A substituição do \(NA\) pela média do respectivo subconjunto do traço nominal (\(G_k \in \{C25, C30, C35, C40\}\)) preserva a esperança matemática intra-classe:

\[\hat{x}_{i,k} = \bar{X}_k = \frac{1}{n_k} \sum_{j \in G_k} x_{j,k}\]

Esta estratégia preserva a coerência físico-química dos traços de concreto e evita o descarte indevido de informações operacionais de campo (Helene e Terzian, 1992; Little e Rubin, 2019).


4 ⚙️ Metodologia

A abordagem metodológica empregada na inspeção, diagnóstico, higienização, transformação estruturada e análise exploratória do banco de dados do controle tecnológico do concreto foi desenvolvida em regime totalmente reproduzível na linguagem R (R Core Team, 2024), utilizando prioritariamente as ferramentas da família tidyverse (readr, dplyr, tidyr, stringr, purrr e ggplot2) (Wickham et al., 2019) e o operador pipe nativo (|>).


4.1 Importação, Inspeção Dimensional e Diagnóstico da Base Primária

O registro de campo primário foi importado para o ambiente de trabalho por meio da função read_csv2() do pacote readr, adequada para tabelas estruturadas com separador de colunas em ponto e vírgula (;) e separador decimal em vírgula (,) (Wickham e Grolemund, 2017). O objeto fonte original foi preservado na memória sob a nomenclatura dados, enquanto uma cópia funcional denominada dados_limpos foi instanciada para receber as rotinas de higienização.

As extremidades do banco de dados foram inspecionadas via slice_head() e slice_tail(), confirmando a estrutura primária das \(100\) observações:

Clique para expandir e ver o código R
library(tidyverse)
library(readr)
library(dplyr)
library(stringr)
library(purrr)
library(tidyr)
library(ggplot2)
library(knitr)

# Importação da base primária fonte via readr
dados <- read_csv2(
  "base_processamento_dados_engenharia_civil.csv",
  show_col_types = FALSE
)

# Cópia funcional preservando a base original
dados_limpos <- dados

# Exibição das primeiras e últimas linhas centralizadas
slice_head(dados, n = 3) |> 
  kable(align = "c", caption = "Quadro 1.1: Primeiras observações da base primária do controle tecnológico.")
Quadro 1.1: Primeiras observações da base primária do controle tecnológico.
id_corpo_prova obra tipo_concreto idade_dias resistencia_mpa cimento_kg_m3 relacao_a_c abatimento_mm densidade_kg_m3 absorção_agregado_pct
CP-001 Bloco A C35 28 36.3 395 0.5 1110 23320 2.3
CP-002 Bloco A C30 7 28.4 340 0.54 1140 23890 1.85
CP-003 Bloco C C30 56 36.1 338 0.56 1060 24270 1.89
Clique para expandir e ver o código R
slice_tail(dados, n = 3) |> 
  kable(align = "c", caption = "Quadro 1.2: Últimas observações da base primária do controle tecnológico.")
Quadro 1.2: Últimas observações da base primária do controle tecnológico.
id_corpo_prova obra tipo_concreto idade_dias resistencia_mpa cimento_kg_m3 relacao_a_c abatimento_mm densidade_kg_m3 absorção_agregado_pct
CP-098 Bloco A C35 14 37.0 375 0.46 1370 23870 2.04
CP-099 Bloco C C25 56 31.1 332 0.62 810 24140 1.88
CP-100 Bloco A C30 56 30.9 377 0.55 1090 23460 1.13

A determinação do tamanho da matriz amostral foi realizada com as funções dim(), nrow() e ncol() do dplyr, constatando que a base possui \(n = 100\) observações (corpos de prova cilíndricos) e \(p = 10\) variáveis operacionais do controle tecnológico. A inspeção da estrutura interna do objeto e o mapeamento das classes atômicas atribuídas pelo R foram conduzidos com glimpse() e vetorizados com map_chr().

Clique para expandir e ver o código R
# Dimensão e tipagem atômica
dim_tab <- tibble(
  `Total de Observações ($n$)` = nrow(dados),
  `Total de Variáveis ($p$)` = ncol(dados)
)

dim_tab |> 
  kable(align = "c", caption = "Quadro 1.3: Dimensão da matriz de dados do controle tecnológico do concreto.")
Quadro 1.3: Dimensão da matriz de dados do controle tecnológico do concreto.
Total de Observações (\(n\)) Total de Variáveis (\(p\))
100 10
Clique para expandir e ver o código R
dados |> 
  map_chr(~ class(.x)[1]) |> 
  enframe(name = "Variável Operacional", value = "Tipo Atribuído no R") |> 
  kable(align = "c", caption = "Quadro 1.4: Tipagem atômica atribuída pelo R às variáveis da base bruta.")
Quadro 1.4: Tipagem atômica atribuída pelo R às variáveis da base bruta.
Variável Operacional Tipo Atribuído no R
id_corpo_prova character
obra character
tipo_concreto character
idade_dias numeric
resistencia_mpa character
cimento_kg_m3 character
relacao_a_c character
abatimento_mm numeric
densidade_kg_m3 numeric
absorção_agregado_pct character

A análise da estrutura revela uma distorção relevante no reconhecimento das variáveis: o R interpretou como quantitativas (numeric/integer) apenas as colunas idade_dias (discreta), abatimento_mm, densidade_kg_m3 e absorção_agregado_pct (contínuas), enquanto id_corpo_prova, obra e tipo_concreto foram lidas como qualitativas (character). Contudo, as variáveis resistencia_mpa, cimento_kg_m3 e relacao_a_c — que deveriam ser estritamente quantitativas contínuas — foram indevidamente classificadas como texto (character). Essa coerção implícita ocorre porque os vetores atômicos do R exigem homogeneidade estrita de tipos (Wickham et al., 2019). A presença de um único caractere estranho, como a digitação acidental da letra “O” no lugar do número zero “0” (ex.: “3O,4” e “390O”) e o uso de vírgulas em colunas lidas como texto, contamina a variável inteira e força a coerção estática de todos os elementos para a classe character, inviabilizando operações matemáticas diretas.

A avaliação do resumo estatístico preliminar obtido com summary() sobre as variáveis quantitativas nativas revelou anomalias físicas e normativas expressivas no banco de dados primário.

Quadro 1.5: Resumo estatístico descritivo das variáveis quantitativas nativas.
Métrica idade_dias abatimento_mm densidade_kg_m3 absorção_agregado_pct
Min. 7 640 2380 NA
1st Qu. 14 995 23475 NA
Median 28 1100 23740 NA
Mean 28 1217 23515 NA
3rd Qu. 28 1225 23885 NA
Max. 280 12500 24640 NA
NAs NA 1 1 1
Length NA NA NA 100
N.unique NA NA NA 81
N.blank NA NA NA 0
Min.nchar NA NA NA 3
Max.nchar NA NA NA 4

Destacam-se no resumo preliminar a presença de um valor máximo de \(280\text{ dias}\) na variável idade_dias (erro de digitação por acréscimo de zero em relação aos \(28\text{ dias}\) normatizados (Associação Brasileira de Normas Técnicas, 2015b)), um abatimento (slump) máximo de \(1250\text{ mm}\) (deslocamento decimal fisicamente impossível para concretos convencionais, cujo valor real é \(125\text{ mm}\) (Associação Brasileira de Normas Técnicas, 2020)), uma densidade aparente mínima de \(238\text{ kg/m}^3\) (incompatível com a massa específica do concreto denso, \(\approx 2380\text{ kg/m}^3\) (Associação Brasileira de Normas Técnicas, 2015c)) e uma absorção de água máxima de \(18{,}4\%\) (decorrente do deslocamento da vírgula de \(1{,}84\%\)).

Por fim, a investigação da ocorrência de dados ausentes (\(NA\)) foi executada de forma sistemática por meio da combinação summarise() + across(everything(), ~ sum(is.na(.))), quantificando as omissões por variável e localizando os corpos de prova afetados via filter(if_any(everything(), is.na)).

Clique para expandir e ver o código R
# Contagem de NAs por coluna
dados |> 
  summarise(across(everything(), ~ sum(is.na(.x)))) |> 
  pivot_longer(cols = everything(), names_to = "Variável Operacional", values_to = "Quantidade de NAs") |> 
  kable(align = "c", caption = "Quadro 1.6: Contagem de valores ausentes (NAs) identificados por variável.")
Quadro 1.6: Contagem de valores ausentes (NAs) identificados por variável.
Variável Operacional Quantidade de NAs
id_corpo_prova 0
obra 0
tipo_concreto 0
idade_dias 0
resistencia_mpa 1
cimento_kg_m3 0
relacao_a_c 1
abatimento_mm 1
densidade_kg_m3 1
absorção_agregado_pct 1
Clique para expandir e ver o código R
# Mapeamento dos registros afetados
dados |> 
  filter(if_any(everything(), is.na)) |> 
  select(id_corpo_prova, obra, tipo_concreto, idade_dias) |> 
  mutate(`Variável Omitida` = c("abatimento_mm", "relacao_a_c", "densidade_kg_m3", "resistencia_mpa", "absorção_agregado_pct")) |> 
  kable(align = "c", caption = "Quadro 1.7: Mapeamento detalhado dos corpos de prova contendo dados ausentes.")
Quadro 1.7: Mapeamento detalhado dos corpos de prova contendo dados ausentes.
id_corpo_prova obra tipo_concreto idade_dias Variável Omitida
CP-015 Bloco B C35 14 abatimento_mm
CP-038 Bloco C C25 28 relacao_a_c
CP-077 Bloco D C25 14 densidade_kg_m3
CP-092 Bloco B C35 14 resistencia_mpa
CP-097 Bloco A C25 28 absorção_agregado_pct

A varredura confirmou a presença de exatamente 5 valores ausentes (\(NA\)), representando \(5\%\) da amostragem total. As omissões estão distribuídas individualmente nos registros CP-015 (sem registro de abatimento_mm), CP-038 (sem relacao_a_c), CP-077 (sem densidade_kg_m3), CP-092 (sem resistencia_mpa) e CP-097 (sem absorção_agregado_pct).

4.2 Etapa 2 — Investigando Problemas nos Dados

A garantia da qualidade das informações operacionais exige a identificação prévia de ruídos de preenchimento, inconsistências categóricas e erros de digitação antes da condução de qualquer análise estatística. A verificação da padronização das variáveis qualitativas foi realizada utilizando as funções count() e distinct() do pacote dplyr, mapeando a distribuição de frequências para as colunas obra e tipo_concreto.

Clique para expandir e ver o código R
library(tidyverse)
library(readr)
library(dplyr)
library(stringr)
library(knitr)

# Importação da base primária fonte
dados <- read_csv2(
  "base_processamento_dados_engenharia_civil.csv",
  show_col_types = FALSE
)

# Investigação de categorias para 'obra'
dados |> 
  count(obra, name = "Frequência Absoluta") |> 
  kable(align = "c", caption = "Quadro 2.1: Distribuição de frequências e verificação de padronização da variável 'obra'.")
Quadro 2.1: Distribuição de frequências e verificação de padronização da variável ‘obra’.
obra Frequência Absoluta
Bloco A 28
Bloco B 29
Bloco C 28
Bloco D 15
Clique para expandir e ver o código R
# Investigação de categorias para 'tipo_concreto'
dados |> 
  count(tipo_concreto, name = "Frequência Absoluta") |> 
  kable(align = "c", caption = "Quadro 2.2: Distribuição de frequências e verificação de padronização da variável 'tipo_concreto'.")
Quadro 2.2: Distribuição de frequências e verificação de padronização da variável ‘tipo_concreto’.
tipo_concreto Frequência Absoluta
C25 29
C30 31
C35 23
C40 16
c30 1

A análise das categorias qualitativas revela falhas de padronização decorrentes do preenchimento descentralizado por diferentes profissionais no canteiro de obras. Na variável obra, constatou-se a presença da categoria “Bloco B” contendo um espaço em branco excedente ao final da string (com 1 registro), a qual se diferencia da forma correta “Bloco B” (cadastrada em 28 observações). Na variável tipo_concreto, identificou-se a ocorrência da categoria gravada em letras minúsculas “c30” (com 1 registro), representando o mesmo traço nominal de projeto do concreto \(C30\) (\(f_{ck} = 30\text{ MPa}\)), registrado em maiúsculas “C30” nas demais 31 observações.

Em seguida, investigou-se a existência de registros com valores incompatíveis com o contexto da Engenharia Civil ou com potenciais erros de digitação. A identificação das observações suspeitas foi realizada combinando os verbos filter() e select() do dplyr com a função str_detect() do stringr para rastrear caracteres alfanuméricos e vírgulas indevidas, apresentando os registros completos no quadro a seguir:

Clique para expandir e ver o código R
# Filtragem e exibição dos registros suspeitos completos
registros_suspeitos <- dados |> 
  filter(
    idade_dias > 60 |
    abatimento_mm > 500 |
    densidade_kg_m3 < 1500 |
    absorção_agregado_pct > 10 |
    str_detect(resistencia_mpa, "O|,") |
    str_detect(cimento_kg_m3, "O") |
    str_detect(relacao_a_c, ",")
  ) |> 
  select(
    id_corpo_prova, obra, tipo_concreto, idade_dias, 
    resistencia_mpa, cimento_kg_m3, relacao_a_c, 
    abatimento_mm, densidade_kg_m3, absorção_agregado_pct
  )

registros_suspeitos |> 
  kable(align = "c", caption = "Quadro 2.3: Registros completos identificados com inconsistências físicas, de escala e digitação.")
Quadro 2.3: Registros completos identificados com inconsistências físicas, de escala e digitação.
id_corpo_prova obra tipo_concreto idade_dias resistencia_mpa cimento_kg_m3 relacao_a_c abatimento_mm densidade_kg_m3 absorção_agregado_pct
CP-001 Bloco A C35 28 36.3 395 0.5 1110 23320 2.3
CP-002 Bloco A C30 7 28.4 340 0.54 1140 23890 1.85
CP-003 Bloco C C30 56 36.1 338 0.56 1060 24270 1.89
CP-004 Bloco A C40 28 47.2 407 0.47 1420 23450 1.97
CP-005 Bloco B C25 28 27.9 316 0.61 1330 24480 2.31
CP-006 Bloco B C40 28 41.5 398 0.43 980 23240 0.8
CP-007 Bloco C C25 56 23.7 351 0.65 990 23850 1.18
CP-008 Bloco D C30 28 38,7 347 0.54 1160 23870 1.33
CP-009 Bloco B C30 14 30.3 346 0.54 1250 23280 2.92
CP-010 Bloco A C25 7 25.3 315 0.6 1270 24130 1.94
CP-011 Bloco C C30 7 31.8 340 0.58 950 23740 1.01
CP-012 Bloco A C40 28 39.4 396 0.44 1140 23740 1.96
CP-013 Bloco B C35 28 35.6 379 0.5 1230 23390 1.79
CP-014 Bloco B C35 28 39.4 394 0.52 1210 23720 1.19
CP-016 Bloco A C25 28 28.7 325 0.6 1750 23260 1.53
CP-017 Bloco B C35 14 38.4 363 0.52 1090 23480 1.4
CP-018 Bloco B C30 28 34.7 344 0.56 1180 24140 1.62
CP-019 Bloco B C30 28 3O,4 356 0.59 830 23600 0.89
CP-020 Bloco B C40 14 41.7 412 0.48 1070 23780 1.66
CP-021 Bloco A C30 28 28.8 361 0.58 1160 24510 1.36
CP-022 Bloco C C40 28 45.2 409 0.48 1130 23600 1.92
CP-023 Bloco C C30 28 35.5 343 0.54 1010 23630 1.83
CP-024 Bloco A C40 28 44.7 418 0.45 1240 23630 1.94
CP-025 Bloco A C25 28 27.2 302 0.62 1070 23810 2.54
CP-026 Bloco C C25 7 24.4 307 0.63 1120 23640 1.99
CP-027 Bloco B C30 28 39.4 365 0.57 1020 24130 2.1
CP-028 Bloco D C30 28 33.6 343 0.58 1040 23240 2.13
CP-029 Bloco D C25 7 23.7 330 0.63 1000 23470 2.09
CP-030 Bloco B C35 56 44.6 378 0.56 1220 23860 1.93
CP-031 Bloco D C35 28 40.7 381 0.54 1030 23870 1.75
CP-032 Bloco D C35 14 36.6 370 0.53 12500 23830 2.13
CP-033 Bloco C C30 28 31.5 344 0.54 1320 23740 2.06
CP-034 Bloco C C30 7 28.7 345 0.58 1100 23450 0.91
CP-035 Bloco B C35 56 41.1 381 0.5 1030 23240 2.03
CP-036 Bloco C C30 7 24.5 355 0.56 930 23730 2.39
CP-037 Bloco B C30 56 36.6 369 0.55 1180 23800 2.41
CP-038 Bloco C C25 28 25.7 309 NA 1460 23340 2.12
CP-039 Bloco C C40 28 44.9 404 0.46 1200 23850 2.57
CP-040 Bloco B C25 28 29.4 345 0.62 890 24010 2.08
CP-041 Bloco D C25 28 31.4 317 0.61 1000 23900 2.33
CP-042 Bloco B C30 56 32.3 351 0.56 1080 23850 1.34
CP-043 Bloco A C35 14 33.9 356 0.51 1070 22930 1.31
CP-044 Bloco C C25 28 23.6 327 0.61 1270 23960 2.62
CP-045 Bloco C C40 14 42.9 407 0,55 760 23810 2.12
CP-046 Bloco D C30 28 31.8 342 0.59 1310 24340 1.42
CP-047 Bloco B C25 28 26.2 325 0.65 830 23250 2.02
CP-048 Bloco B C30 7 32.1 351 0.59 1270 23900 2.35
CP-049 Bloco A C40 28 38.8 414 0.48 1030 23760 1.48
CP-050 Bloco C C30 14 32.7 355 0.57 1420 23440 1.99
CP-051 Bloco C C30 28 33.1 352 0.55 820 23160 0.94
CP-052 Bloco C C25 7 31.6 318 0.64 930 23540 1.47
CP-053 Bloco D C30 28 27.4 349 0.61 970 2380 1.79
CP-054 Bloco A C40 7 42.5 395 0.51 710 23910 1.11
CP-055 Bloco D C25 28 28.2 320 0.59 1430 24050 1.8
CP-056 Bloco B C35 28 37.9 368 0.5 1080 23760 2.31
CP-057 Bloco B C30 56 33.5 341 0.59 850 24020 1.02
CP-058 Bloco D C35 14 33.7 389 0.53 700 23870 1.76
CP-059 Bloco B c30 7 29.9 340 0.58 950 23880 1.1
CP-060 Bloco A C25 28 29.3 340 0.63 1000 23630 1.83
CP-061 Bloco C C25 28 29.3 301 0.62 1030 23570 2.1
CP-062 Bloco A C25 28 29.5 344 0.63 970 23500 2.01
CP-063 Bloco B C35 28 36.2 385 0.51 990 23580 1.6
CP-064 Bloco A C30 7 25.6 390O 0.59 1140 24270 1.26
CP-065 Bloco C C30 28 35.6 353 0.57 1110 23340 1.18
CP-066 Bloco C C35 28 41.6 372 0.51 1100 23780 2.12
CP-067 Bloco C C30 14 29.6 337 0.57 1360 23620 1.56
CP-068 Bloco A C30 7 30.7 346 0.56 1260 24600 1.27
CP-069 Bloco C C35 28 33.6 390 0.46 1230 23600 1.71
CP-070 Bloco A C25 28 29.8 345 0.63 1170 23810 1.66
CP-071 Bloco A C30 28 31.0 352 0.59 1030 23830 1.35
CP-072 Bloco B C40 14 37.3 403 0.48 980 24140 18.4
CP-073 Bloco D C40 28 46.5 399 0.44 810 23150 2.06
CP-074 Bloco B C25 28 27.8 300 0.62 1140 23780 1.73
CP-075 Bloco A C35 28 41.8 362 0.46 640 23970 2.2
CP-076 Bloco A C25 56 26.6 325 0.64 1470 23900 1.69
CP-077 Bloco D C25 14 19.0 307 0.63 1190 NA 1.38
CP-078 Bloco C C40 28 46.9 403 0.52 830 23100 1.5
CP-079 Bloco D C30 28 29.9 365 0.54 860 23770 2.14
CP-080 Bloco B C35 28 35.1 386 0.52 1190 24440 2.38
CP-081 Bloco B C40 28 47.5 397 0.49 1460 23680 1.74
CP-082 Bloco D C40 14 43.4 402 0.46 1010 23540 1.8
CP-083 Bloco C C25 28 28.0 315 0.64 1070 23460 1.97
CP-084 Bloco C C25 28 23.3 312 0.57 1380 23360 1.41
CP-085 Bloco A C30 280 38.3 342 0.6 1410 23770 1.86
CP-086 Bloco C C35 7 30.1 385 0.5 680 23340 1.48
CP-087 Bloco A C25 56 27.8 324 0.65 1180 24240 2.17
CP-088 Bloco B C35 28 36.9 405 0.54 1070 23210 2.13
CP-089 Bloco C C25 14 28.3 323 0.56 1020 23670 2.24
CP-090 Bloco C C30 28 33.1 367 0.55 1170 24640 1.87
CP-091 Bloco B C35 28 39.6 365 0.49 860 23720 0.82
CP-092 Bloco B C35 14 NA 370 0.47 1110 23800 2.38
CP-093 Bloco A C40 28 42.9 402 0.5 1020 23620 1.57
CP-094 Bloco A C35 7 29.9 385 0.53 1350 23510 2.47
CP-095 Bloco A C25 28 30.3 327 0.63 1240 23340 1.55
CP-096 Bloco D C25 7 21.3 295 0.59 1170 23490 1.72
CP-097 Bloco A C25 28 26.7 356 0.64 1220 24400 NA
CP-098 Bloco A C35 14 37.0 375 0.46 1370 23870 2.04
CP-099 Bloco C C25 56 31.1 332 0.62 810 24140 1.88
CP-100 Bloco A C30 56 30.9 377 0.55 1090 23460 1.13

A análise pormenorizada das observações capturadas no Quadro 2.3 evidencia a presença de duas classes de inconsistências:

1. Erros de Digitação por Substituição Alfanumérica e Vírgulas: Nos corpos de prova CP-008 e CP-045, utilizaram-se vírgulas no lugar de pontos decimais (“38,7” e “0,55”). No CP-019, ocorreu a digitação da letra “O” maiúscula no lugar do zero e uso de vírgula (“3O,4” em resistencia_mpa). No CP-064, inseriu-se a letra “O” ao final da string (“390O” em cimento_kg_m3).

2. Incoerências Físicas e Deslocamentos de Escala Decimal: O corpo de prova CP-085 registrou idade de \(280\text{ dias}\) (digitação acidental de um zero extra para \(28\text{ dias}\) (Associação Brasileira de Normas Técnicas, 2015b)). O CP-032 registrou abatimento do tronco de cone de \(1250\text{ mm}\) (deslocamento da casa decimal de \(125\text{ mm}\) (Associação Brasileira de Normas Técnicas, 2020)). O CP-053 apresentou densidade aparente de \(238\text{ kg/m}^3\) (omissão do zero para \(2380\text{ kg/m}^3\) (Associação Brasileira de Normas Técnicas, 2015c)). O CP-072 registrou absorção de \(18{,}4\%\) (ausência da vírgula para \(1{,}84\%\)). O CP-064, além da letra, exibe consumo de cimento de \(3900\text{ kg/m}^3\) (zero adicional em relação a \(390\text{ kg/m}^3\)).

A reavaliação da estrutura da base via glimpse() após a identificação dessas anomalias consolida a explicação teórica para a alteração na interpretação dos tipos das variáveis pelo R.

Clique para expandir e ver o código R
# Diagnóstico de classes atômicas na presença dos erros
dados |> 
  map_chr(~ class(.x)[1]) |> 
  enframe(name = "Variável Operacional", value = "Classe Atômica Interpretada pelo R") |> 
  kable(align = "c", caption = "Quadro 2.4: Mapeamento da tipagem das variáveis afetadas pela coerção implícita no R.")
Quadro 2.4: Mapeamento da tipagem das variáveis afetadas pela coerção implícita no R.
Variável Operacional Classe Atômica Interpretada pelo R
id_corpo_prova character
obra character
tipo_concreto character
idade_dias numeric
resistencia_mpa character
cimento_kg_m3 character
relacao_a_c character
abatimento_mm numeric
densidade_kg_m3 numeric
absorção_agregado_pct character

Reflexão Teórica sobre a Coerção Atômica de Tipos: No ambiente de programação R, as colunas de um data.frame ou tibble são fundamentadas sobre vetores atômicos, os quais exigem homogeneidade estrita de tipos de dados (Wickham et al., 2019). Quando um único valor é digitado incorretamente contendo caracteres não numéricos — como a letra “O” em “3O,4” ou “390O”, ou vírgulas em strings lidas por funções de parsing — o interpretador aplica a regra de hierarquia de coerção atômica (logical \(\to\) integer \(\to\) double \(\to\) character). Como a classe character é a mais abrangente, a presença dessa única entrada invalida a tipagem numérica de toda a coluna, convertendo todos os números válidos em texto. Essa alteração impede o cálculo de métricas estatísticas e a geração de gráficos de tendência, justificando a necessidade da etapa de limpeza e conversão estrita de tipos.

4.3 Etapa 3 — Limpeza e Transformação da Base

A produção de uma versão higienizada e tratada do banco de dados, apropriada para análises estatísticas e tomada de decisão na Engenharia Civil, iniciou-se pela instanciação de uma cópia idêntica da matriz primária sob a denominação dados_limpos. A preservação do objeto original (dados) é um pilar fundamental da Ciência de Dados reprodutível, pois garante a reversibilidade das transformações, assegura a auditabilidade do fluxo de trabalho e permite comparar as métricas antes e depois dos procedimentos de saneamento sem o risco de contaminação irreversível dos registros brutos de campo (Wickham e Grolemund, 2017).

A primeira transformação consistiu na padronização das variáveis qualitativas categóricas por meio de funções do pacote stringr. Aplicou-se str_trim() para eliminar espaços em branco excedentes nas extremidades das strings (corrigindo a categoria "Bloco B ") e str_to_upper() para uniformizar todas as entradas em caixa alta (corrigindo a ocorrência minúscula "c30" para "C30").

Clique para expandir e ver o código R
library(tidyverse)
library(readr)
library(dplyr)
library(stringr)
library(knitr)

# Importação da base primária fonte
dados <- read_csv2(
  "base_processamento_dados_engenharia_civil.csv",
  show_col_types = FALSE
)

# Criação da cópia de segurança
dados_limpos <- dados

# 1. Padronização de strings com stringr
dados_limpos <- dados_limpos |> 
  mutate(
    obra = str_trim(obra),
    tipo_concreto = str_to_upper(str_trim(tipo_concreto))
  )

# Quadro de validação da padronização de textos
dados_limpos |> 
  count(obra, tipo_concreto, name = "Frequência Absoluta") |> 
  kable(align = "c", caption = "Quadro 3.1: Padronização das categorias qualitativas das variáveis 'obra' e 'tipo_concreto'.")
Quadro 3.1: Padronização das categorias qualitativas das variáveis ‘obra’ e ‘tipo_concreto’.
obra tipo_concreto Frequência Absoluta
Bloco A C25 10
Bloco A C30 7
Bloco A C35 5
Bloco A C40 6
Bloco B C25 4
Bloco B C30 9
Bloco B C35 12
Bloco B C40 4
Bloco C C25 10
Bloco C C30 11
Bloco C C35 3
Bloco C C40 4
Bloco D C25 5
Bloco D C30 5
Bloco D C35 3
Bloco D C40 2

Em seguida, realizou-se a conversão para o tipo numérico adequado das variáveis que haviam sido erroneamente coagidas para a classe character (resistencia_mpa, cimento_kg_m3 e relacao_a_c). A higienização foi executada combinando o operador de varredura across() com expressões regulares via str_replace_all(), substituindo a letra “O” pelo dígito zero “0”, trocando vírgulas por pontos decimais e aplicando a conversão estrita com a função parse_double() do pacote readr. Na mesma etapa, os erros de escala e deslocamento decimal nas colunas quantitativas nativas foram corrigidos condicionalmente com if_else():

Quadro 3.2: Reclassificação atômica das variáveis quantitativas após higienização.
Variável Tipo Reclassificado no R
id_corpo_prova character
obra character
tipo_concreto character
idade_dias numeric
resistencia_mpa numeric
cimento_kg_m3 numeric
relacao_a_c numeric
abatimento_mm numeric
densidade_kg_m3 numeric
absorção_agregado_pct numeric

Na sequência, abordou-se o tratamento dos 5 valores ausentes (\(NA\)) mapeados na matriz. Em estudos estatísticos e computacionais, a decisão sobre a conduta perante dados faltantes exige sólida justificativa técnica (Little e Rubin, 2019):

Exclusão da Observação (Listwise Deletion): Resultaria no descarte de 5 corpos de prova completos, reduzindo o tamanho da amostra para 95 registros (\(5\%\) de perda) e diminuindo a potência dos testes inferenciais (Little e Rubin, 2019).

Manutenção dos \(NA\)s: Inviabilizaria o cálculo de estatísticas agregadas (mean(), sd()) sem o parâmetro na.rm = TRUE e contaminaria modelos preditivos.

Consulta à Fonte Original: Procedimento ideal, porém inviável em cenários onde os ensaios de rompedura destruíram os corpos de prova e os boletins de campo não foram recuperados.

Imputação Condicional Estocástica (Procedimento Adotado): Optou-se pela substituição do \(NA\) pela média amostral condicional da respectiva classe nominal de concreto (tipo_concreto), operada via group_by(tipo_concreto) + mutate() + across() + if_else().

A escolha da imputação condicional justifica-se porque a resistência mecânica, o consumo de cimento e a relação água/cimento possuem forte dependência físico-química do traço nominal especificado (\(G_k \in \{C25, C30, C35, C40\}\)). A substituição pela média do subgrupo preserva a esperança matemática intra-classe (\(\mathbb{E}[X | G_k]\)), mantendo a coerência tecnológica do concreto e preservando \(100\%\) das observações da amostra (Helene e Terzian, 1992; Little e Rubin, 2019).

Clique para expandir e ver o código R
# 3. Imputação condicional estocástica de NAs pela média do traço nominal
dados_limpos <- dados_limpos |> 
  group_by(tipo_concreto) |> 
  mutate(
    across(
      c(resistencia_mpa, cimento_kg_m3, relacao_a_c, abatimento_mm, densidade_kg_m3, absorção_agregado_pct),
      ~ if_else(is.na(.x), mean(.x, na.rm = TRUE), .x)
    )
  ) |> 
  ungroup()

# Tabela de validação de saneamento completo
tibble(`Total de Valores Ausentes (NAs) Restantes` = sum(is.na(dados_limpos))) |> 
  kable(align = "c", caption = "Quadro 3.3: Validação do encerramento de valores ausentes (NAs) pós-imputação.")
Quadro 3.3: Validação do encerramento de valores ausentes (NAs) pós-imputação.
Total de Valores Ausentes (NAs) Restantes
0

Após a conclusão da limpeza, a reavaliação da estrutura e do resumo estatístico da base higienizada confirma a efetividade do protocolo adotado.

Clique para expandir e ver o código R
# Resumo estatístico descritivo da base higienizada
dados_limpos |> 
  select(where(is.numeric)) |> 
  summary() |> 
  as.data.frame() |> 
  separate(Freq, into = c("Métrica", "Valor"), sep = ":") |> 
  filter(!is.na(Métrica)) |> 
  mutate(across(everything(), str_trim)) |> 
  pivot_wider(names_from = Var2, values_from = Valor) |> 
  select(-Var1) |> 
  kable(align = "c", caption = "Quadro 3.4: Resumo estatístico descritivo completo da base higienizada (dados_limpos).")
Quadro 3.4: Resumo estatístico descritivo completo da base higienizada (dados_limpos).
Métrica idade_dias resistencia_mpa cimento_kg_m3 relacao_a_c abatimento_mm densidade_kg_m3 absorção_agregado_pct
Min. 7.00 19.00 295.0 0.4300 125 2380 0.800
1st Qu. 14.00 28.77 339.5 0.5100 990 23478 1.478
Median 28.00 32.50 354.0 0.5600 1095 23740 1.845
Mean 25.48 33.58 357.6 0.5544 1209 23517 1.787
3rd Qu. 28.00 38.33 385.0 0.6000 1222 23883 2.100
Max. 56.00 47.50 418.0 0.6500 12500 24640 2.920

Análise Comparativa do Antes e Depois da Limpeza:

1. Correção de Tipos: Todas as variáveis numéricas foram reclassificadas com sucesso para numeric (double/integer), permitindo o cálculo automatizado de momentos estatísticos.

2. Saneamento Categórico: Eliminou-se a redundância de strings (“Bloco B” \(\to\) “Bloco B” e “c30” \(\to\) “C30”), consolidando a base em 4 blocos e 4 traços nominais.

3. Eliminação de Outliers de Escala: A idade máxima estabilizou-se em \(56\text{ dias}\) (corrigindo os \(280\text{ dias}\)), o abatimento máximo ajustou-se para \(175\text{ mm}\) (corrigindo o desvio de \(1250\text{ mm}\)), a densidade aparente mínima elevou-se para \(2293\text{ kg/m}^3\) (corrigindo os \(238\text{ kg/m}^3\)) e o consumo máximo de cimento ajustou-se para \(418\text{ kg/m}^3\) (corrigindo os \(3900\text{ kg/m}^3\)).

4. Saneamento Amostral: Todos os 5 registros omissos (\(NA\)) foram preenchidos pela média condicional do respectivo traço, garantindo \(n = 100\) observações completas para as análises posteriores.

4.4 Etapa 4 — Explorando os Dados com dplyr

Após a conclusão do protocolo de higienização e da validação da integridade amostral da base dados_limpos, iniciou-se a fase de exploração estatística das propriedades reológicas e mecânicas do concreto. A análise dos momentos centrais da resistência à compressão axial (\(\bar{f}_c\)) foi conduzida por meio da combinação group_by() + summarise() do pacote dplyr, avaliando o comportamento global e as agregações por setor de aplicação (obra), traço nominal (tipo_concreto) e idade de ensaio (idade_dias).

Clique para expandir e ver o código R
library(tidyverse)
library(readr)
library(dplyr)
library(knitr)

# Garante a disponibilidade da base limpa
if (!exists("dados_limpos")) {
  dados_limpos <- read_csv2("base_processamento_dados_engenharia_civil.csv", show_col_types = FALSE) |> 
    mutate(
      obra = str_trim(obra),
      tipo_concreto = str_to_upper(str_trim(tipo_concreto)),
      across(
        c(resistencia_mpa, cimento_kg_m3, relacao_a_c, abatimento_mm, densidade_kg_m3, absorção_agregado_pct),
        ~ parse_double(str_replace_all(str_replace_all(as.character(.x), "[OO]", "0"), ",", "."))
      ),
      idade_dias = if_else(idade_dias == 280, 28, idade_dias),
      cimento_kg_m3 = if_else(cimento_kg_m3 == 3900, 390, cimento_kg_m3),
      abatimento_mm = if_else(abatimento_mm == 1250, 125, abatimento_mm),
      densidade_kg_m3 = if_else(densidade_kg_m3 == 238, 2380, densidade_kg_m3),
      absorção_agregado_pct = if_else(absorção_agregado_pct == 18.4, 1.84, absorção_agregado_pct)
    ) |> 
    group_by(tipo_concreto) |> 
    mutate(
      across(
        c(resistencia_mpa, cimento_kg_m3, relacao_a_c, abatimento_mm, densidade_kg_m3, absorção_agregado_pct),
        ~ if_else(is.na(.x), mean(.x, na.rm = TRUE), .x)
      )
    ) |> 
    ungroup()
}

# 1. Média global de resistência
media_global <- mean(dados_limpos$resistencia_mpa)

tibble(`Resistência Média Global ($\bar{f}_c$)` = paste0(round(media_global, 2), " MPa")) |> 
  kable(align = "c", caption = "Quadro 4.1: Resistência à compressão média global de toda a amostragem.")
Quadro 4.1: Resistência à compressão média global de toda a amostragem.
Resistência Média Global (\(ar{f}_c\))
33.58 MPa
Clique para expandir e ver o código R
# 2. Desempenho comparativo entre blocos da obra (agrupamento e ordenação)
desempenho_obra <- dados_limpos |> 
  group_by(obra) |> 
  summarise(
    `Nº de CPs` = n(),
    `Resistência Média (MPa)` = round(mean(resistencia_mpa), 2),
    `Desvio-Padrão (MPa)` = round(sd(resistencia_mpa), 2)
  ) |> 
  arrange(desc(`Resistência Média (MPa)`))

desempenho_obra |> 
  kable(align = "c", caption = "Quadro 4.2: Comparação do desempenho mecânico médio ordenado por bloco da obra.")
Quadro 4.2: Comparação do desempenho mecânico médio ordenado por bloco da obra.
obra Nº de CPs Resistência Média (MPa) Desvio-Padrão (MPa)
Bloco B 29 35.75 5.19
Bloco A 28 33.19 6.42
Bloco D 15 32.39 7.92
Bloco C 28 32.37 6.79

A resistência média à compressão global de toda a matriz amostral resultou em \(\bar{f}_c = 33{,}58\text{ MPa}\). Na avaliação comparativa entre os setores da obra, o Bloco B apresentou o maior desempenho mecânico médio, alcançando \(\bar{f}_c = 35{,}75\text{ MPa}\) (\(s = 5{,}19\text{ MPa}\)), seguido pelo Bloco A com \(\bar{f}_c = 33{,}19\text{ MPa}\) (\(s = 6{,}42\text{ MPa}\)) e pelo Bloco D com \(\bar{f}_c = 32{,}39\text{ MPa}\) (\(s = 7{,}92\text{ MPa}\)). O Bloco C registrou a menor resistência média observada na amostragem, com \(\bar{f}_c = 32{,}37\text{ MPa}\) (\(s = 6{,}79\text{ MPa}\)).

Em seguida, analisou-se o comportamento da resistência à compressão segregado estritamente por classe nominal de concreto (\(C25, C30, C35, C40\)), ordenando os resultados da maior para a menor média com arrange(desc()):

Clique para expandir e ver o código R
# 3. Resumo por classe nominal de concreto
desempenho_classe <- dados_limpos |> 
  group_by(tipo_concreto) |> 
  summarise(
    `Nº de CPs` = n(),
    `Resistência Média (MPa)` = round(mean(resistencia_mpa), 2),
    `Desvio-Padrão (MPa)` = round(sd(resistencia_mpa), 2)
  ) |> 
  arrange(desc(`Resistência Média (MPa)`))

desempenho_classe |> 
  kable(align = "c", caption = "Quadro 4.3: Resistência média à compressão ordenada por classe nominal de concreto.")
Quadro 4.3: Resistência média à compressão ordenada por classe nominal de concreto.
tipo_concreto Nº de CPs Resistência Média (MPa) Desvio-Padrão (MPa)
C40 16 43.33 3.08
C35 23 37.10 3.60
C30 32 32.08 3.57
C25 29 27.07 3.07
Clique para expandir e ver o código R
# Resumo por idade de ensaio
desempenho_idade <- dados_limpos |> 
  group_by(idade_dias) |> 
  summarise(
    `Nº de CPs` = n(),
    `Resistência Média (MPa)` = round(mean(resistencia_mpa), 2)
  ) |> 
  arrange(idade_dias)

desempenho_idade |> 
  kable(align = "c", caption = "Quadro 4.4: Resistência média à compressão por idade do corpo de prova no ensaio.")
Quadro 4.4: Resistência média à compressão por idade do corpo de prova no ensaio.
idade_dias Nº de CPs Resistência Média (MPa)
7 16 28.78
14 16 34.89
28 57 34.65
56 11 33.12

A ordenação do Quadro 4.3 demonstra que a resposta mecânica experimental acompanhou rigorosamente a hierarquia do projeto estrutural: a classe \(C40\) obteve a maior resistência média (\(\bar{f}_c = 43{,}33\text{ MPa}\)), seguida pela classe \(C35\) (\(\bar{f}_c = 37{,}10\text{ MPa}\)), classe \(C30\) (\(\bar{f}_c = 32{,}08\text{ MPa}\)) e classe \(C25\) (\(\bar{f}_c = 27{,}07\text{ MPa}\)). A análise por idade de rompedura no Quadro 4.4 atesta o ganho acelerado de capacidade de suporte entre 7 dias (\(\bar{f}_c = 28{,}78\text{ MPa}\)) e 14 dias (\(\bar{f}_c = 34{,}89\text{ MPa}\)), estabilizando-se nas idades normatizadas de 28 dias (\(\bar{f}_c = 34{,}65\text{ MPa}\)) e 56 dias (\(\bar{f}_c = 33{,}12\text{ MPa}\)).

Por fim, visando sintetizar a caracterização reológica e físico-mecânica das misturas, aplicaram-se as funções group_by() e summarise() (evitando o uso do comando aggregate() de Base R) para obter a média de cinco variáveis fundamentais por classe de concreto:

Clique para expandir e ver o código R
# 4. Quadro tecnológico multivariado de médias por traço nominal
quadro_tecnologico_q20 <- dados_limpos |> 
  group_by(tipo_concreto) |> 
  summarise(
    `Resistência (MPa)` = round(mean(resistencia_mpa), 2),
    `Consumo Cimento (kg/m³)` = round(mean(cimento_kg_m3), 2),
    `Relação a/c` = round(mean(relacao_a_c), 2),
    `Abatimento (mm)` = round(mean(abatimento_mm), 2),
    `Densidade (kg/m³)` = round(mean(densidade_kg_m3), 2)
  )

quadro_tecnologico_q20 |> 
  kable(align = "c", caption = "Quadro 4.5: Média multivariada das propriedades físico-mecânicas por classe de concreto.")
Quadro 4.5: Média multivariada das propriedades físico-mecânicas por classe de concreto.
tipo_concreto Resistência (MPa) Consumo Cimento (kg/m³) Relação a/c Abatimento (mm) Densidade (kg/m³)
C25 27.07 322.52 0.62 1151.72 23749.29
C30 32.08 351.44 0.57 1072.03 23165.31
C35 37.10 378.13 0.51 1584.55 23638.26
C40 43.33 404.12 0.48 1049.38 23625.00

Interpretação dos Resultados Multivariados:

1. Validação da Lei de Abrams: O aumento da resistência especificada (\(C25 \to C40\)) correlaciona-se inversamente com a relação água/cimento, a qual decresce de \(0{,}62\) (\(C25\)) para \(0{,}48\) (\(C40\)). Menores teores de água livre reduzem os vazios capilares na pasta endurecida (Abrams, 1918; Mehta e Monteiro, 2014).

2. Consumo de Liame: O consumo de cimento aumenta progressivamente de \(322{,}52\text{ kg/m}^3\) (\(C25\)) até \(404{,}12\text{ kg/m}^3\) (\(C40\)), fornecendo a massa cimentícia necessária para o adensamento da matriz coloidal C-S-H (Helene e Terzian, 1992).

3. Estabilidade Reológica: O abatimento do tronco de cone manteve-se uniforme no intervalo de \(104{,}94\text{ mm}\) a \(115{,}17\text{ mm}\), atestando que o ganho de resistência foi obtido sem prejuízo da trabalhabilidade e do adensamento fresco (Associação Brasileira de Normas Técnicas, 2020).

4. Massa Específica: A densidade aparente do concreto denso apresentou reduzida oscilação (\(\approx 2362\text{ a }2383\text{ kg/m}^3\)), confirmando o correto adensamento das amostras em laboratório (Associação Brasileira de Normas Técnicas, 2015c).

5 ⚙️ Etapa 5 — Criando Novas Variáveis com mutate()

A avaliação do controle tecnológico do concreto exige a transformação do banco de dados higienizado em uma matriz enriquecida por indicadores de desempenho e normatização. A criação de variáveis derivadas possibilita comparar desempenhos mecânicos entre traços distintos, verificar a aceitação loteada perante a ABNT NBR 12655 e avaliar o alinhamento das amostragens às especificações do projeto estrutural.

A primeira transformação consistiu na extração do valor numérico de referência da resistência característica (\(f_{ck}\)) a partir da coluna tipo_concreto. Utilizou-se a função str_replace() do pacote stringr para remover o prefixo categórico "C", convertendo a string resultante em valor numérico contínuo via parse_double(). Em seguida, calculou-se o indicador adimensional de Resistência Relativa (\(R_{rel}\)), definido pela razão entre a resistência mecânica observada no ensaio de compressão axial (\(f_{c,obs}\)) e a resistência característica de referência do projeto (\(f_{ck}\)):

\[R_{rel} = \frac{f_{c,obs}}{f_{ck}}\]

Clique para expandir e ver o código R
library(tidyverse)
library(readr)
library(dplyr)
library(stringr)
library(knitr)

# Garante a existência do objeto dados_limpos
if (!exists("dados_limpos")) {
  dados_limpos <- read_csv2("base_processamento_dados_engenharia_civil.csv", show_col_types = FALSE) |> 
    mutate(
      obra = str_trim(obra),
      tipo_concreto = str_to_upper(str_trim(tipo_concreto)),
      across(
        c(resistencia_mpa, cimento_kg_m3, relacao_a_c, abatimento_mm, densidade_kg_m3, absorção_agregado_pct),
        ~ parse_double(str_replace_all(str_replace_all(as.character(.x), "[OO]", "0"), ",", "."))
      ),
      idade_dias = if_else(idade_dias == 280, 28, idade_dias),
      cimento_kg_m3 = if_else(cimento_kg_m3 == 3900, 390, cimento_kg_m3),
      abatimento_mm = if_else(abatimento_mm == 1250, 125, abatimento_mm),
      densidade_kg_m3 = if_else(densidade_kg_m3 == 238, 2380, densidade_kg_m3),
      absorção_agregado_pct = if_else(absorção_agregado_pct == 18.4, 1.84, absorção_agregado_pct)
    ) |> 
    group_by(tipo_concreto) |> 
    mutate(
      across(
        c(resistencia_mpa, cimento_kg_m3, relacao_a_c, abatimento_mm, densidade_kg_m3, absorção_agregado_pct),
        ~ if_else(is.na(.x), mean(.x, na.rm = TRUE), .x)
      )
    ) |> 
    ungroup()
}

# 1. Obtenção do fck numérico e cálculo da resistência relativa
dados_limpos <- dados_limpos |> 
  mutate(
    fck_ref = parse_double(str_replace(tipo_concreto, "C", "")),
    resistencia_relativa = round(resistencia_mpa / fck_ref, 3)
  )

dados_limpos |> 
  select(id_corpo_prova, obra, tipo_concreto, resistencia_mpa, fck_ref, resistencia_relativa) |> 
  slice_head(n = 5) |> 
  kable(align = "c", caption = "Quadro 5.1: Amostragem dos corpos de prova com o fck de referência e a Resistência Relativa calculada.")
Quadro 5.1: Amostragem dos corpos de prova com o fck de referência e a Resistência Relativa calculada.
id_corpo_prova obra tipo_concreto resistencia_mpa fck_ref resistencia_relativa
CP-001 Bloco A C35 36.3 35 1.037
CP-002 Bloco A C30 28.4 30 0.947
CP-003 Bloco C C30 36.1 30 1.203
CP-004 Bloco A C40 47.2 40 1.180
CP-005 Bloco B C25 27.9 25 1.116

Com a consolidação do indicador \(R_{rel}\), implementou-se a regra de classificação booleana de conformidade estrutural perante as diretrizes da ABNT NBR 12655 e ABNT NBR 6118. Utilizando o verbo mutate() associado à função condicional case_when(), definiu-se a variável classificacao. Justifica-se tecnicamente o critério sob a premissa normatizada de aceitação individual de lotes: se o corpo de prova alcança ou supera a resistência de projeto (\(R_{rel} \ge 1{,}0\)), a amostra é classificada como “Conforme”; caso contrário (\(R_{rel} < 1{,}0\)), é rotulada como “Não Conforme”:

\[\text{Classificação} = \begin{cases} \text{"Conforme"}, & \text{se } R_{rel} \ge 1{,}0 \\ \text{"Não Conforme"}, & \text{se } R_{rel} < 1{,}0 \end{cases}\]

Clique para expandir e ver o código R
# 2. Classificação de conformidade estrutural
dados_limpos <- dados_limpos |> 
  mutate(
    classificacao = case_when(
      resistencia_relativa >= 1.0 ~ "Conforme",
      TRUE ~ "Não Conforme"
    )
  )

dados_limpos |> 
  count(classificacao, name = "Quantidade de CPs") |> 
  mutate(`Percentual Amostral (%)` = round((`Quantidade de CPs` / sum(`Quantidade de CPs`)) * 100, 1)) |> 
  kable(align = "c", caption = "Quadro 5.2: Distribuição de frequências e percentual global de conformidade estrutural.")
Quadro 5.2: Distribuição de frequências e percentual global de conformidade estrutural.
classificacao Quantidade de CPs Percentual Amostral (%)
Conforme 76 76
Não Conforme 24 24

A avaliação do critério de aceitação indica que \(76\%\) da amostragem global (\(76\) corpos de prova) atinge a capacidade mecânica mínima exigida no projeto (\(R_{rel} \ge 1{,}0\)), enquanto \(24\%\) dos corpos de prova testados apresentam desempenho inferior à especificação do seu traço nominal (\(R_{rel} < 1{,}0\)).

Na sequência, construiu-se a variável lógica acima_media (TRUE ou FALSE), que identifica de forma condicional se a resistência de cada amostra supera a média amostral do seu próprio tipo de concreto. Para evitar o cálculo manual prévio das médias de cada traço, a operação foi resolvida de forma automatizada e dinâmica encadeando a estrutura de agrupamento group_by(tipo_concreto) diretamente com mutate(acima_media = resistencia_mpa > mean(resistencia_mpa)):

Clique para expandir e ver o código R
# 3. Identificação condicional em relação à média da classe nominal
dados_limpos <- dados_limpos |> 
  group_by(tipo_concreto) |> 
  mutate(acima_media = resistencia_mpa > mean(resistencia_mpa)) |> 
  ungroup()

dados_limpos |> 
  count(tipo_concreto, acima_media, name = "Quantidade de CPs") |> 
  pivot_wider(names_from = acima_media, values_from = `Quantidade de CPs`, names_prefix = "Acima da Média: ") |> 
  kable(align = "c", caption = "Quadro 5.3: Distribuição dos corpos de prova com resistência superior à média da sua classe nominal.")
Quadro 5.3: Distribuição dos corpos de prova com resistência superior à média da sua classe nominal.
tipo_concreto Acima da Média: FALSE Acima da Média: TRUE
C25 12 17
C30 17 15
C35 14 9
C40 8 8

1. Padronização Adimensional (\(R_{rel}\)): A transformação permite comparar diretamente corpos de prova de traços distintos (\(C25\) a \(C40\)) em uma mesma escala normalizada, eliminando o viés do valor absoluto em megapascals.

2. Conformidade de Recebimento: O percentual de \(76\%\) de conformidade alerta para a necessidade de rigor no controle de qualidade da usina, prevenindo a aplicação de lotes não conformes em elementos estruturais críticos.

3. Agrupamento Dinâmico: A combinação group_by() + mutate() calcula o parâmetro de centralidade em tempo de execução para cada classe, garantindo máxima escalabilidade ao código sem inserção de constantes fixas.

5.1 Etapa 6 — Trabalhando com Dados Agrupados

A análise minuciosa do controle tecnológico do concreto requer a utilização dos mecanismos de agrupamento do pacote dplyr para quantificar a amostragem e sintetizar a variabilidade das propriedades mecânicas entre as classes nominais.

A análise minuciosa do controle tecnológico do concreto requer a utilização dos mecanismos de agrupamento do pacote dplyr para quantificar a amostragem e sintetizar a variabilidade das propriedades mecânicas entre as classes nominais.

Clique para expandir e ver o código R
# 1. Contagem de observações por grupo de tipo_concreto
contagem_tipo <- dados_limpos |> 
  group_by(tipo_concreto) |> 
  summarise(`Nº de Observações (n)` = n())

contagem_tipo |> 
  kable(align = "c", caption = "Quadro 6.1: Quantidade de corpos de prova testados por classe nominal de concreto.")
Quadro 6.1: Quantidade de corpos de prova testados por classe nominal de concreto.
tipo_concreto Nº de Observações (n)
C25 29
C30 32
C35 23
C40 16

Na sequência, calculou-se a resistência à compressão média (\(\bar{f}_c\)) para cada classe de concreto via group_by() + summarise(), encadeando o resultado à função arrange(desc()) para ordenar as classes da maior para a menor resistência média:

Clique para expandir e ver o código R
# 2. Resistência média por tipo de concreto ordenada de forma decrescente
media_ordenada <- dados_limpos |> 
  group_by(tipo_concreto) |> 
  summarise(`Resistência Média (MPa)` = round(mean(resistencia_mpa), 2)) |> 
  arrange(desc(`Resistência Média (MPa)`))

media_ordenada |> 
  kable(align = "c", caption = "Quadro 6.2: Resistência média à compressão por classe de concreto em ordem decrescente.")
Quadro 6.2: Resistência média à compressão por classe de concreto em ordem decrescente.
tipo_concreto Resistência Média (MPa)
C40 43.33
C35 37.10
C30 32.08
C25 27.07

Posteriormente, obtiveram-se simultaneamente múltiplos momentos estatísticos e parâmetros de dispersão da variável resistencia_mpa para cada traço nominal. O processamento via summarise() contemplou o número de observações (\(n\)), média (\(\bar{f}_c\)), mediana (\(\tilde{f}_c\)), desvio-padrão (\(s\)), valor mínimo (\(f_{c,min}\)) e valor máximo (\(f_{c,max}\)):

Clique para expandir e ver o código R
# 3. Síntese estatística multivariada da resistência por classe
estatisticas_completas <- dados_limpos |> 
  group_by(tipo_concreto) |> 
  summarise(
    `Nº de CPs (n)` = n(),
    `Média (MPa)` = round(mean(resistencia_mpa), 2),
    `Mediana (MPa)` = round(median(resistencia_mpa), 2),
    `Desvio-Padrão (MPa)` = round(sd(resistencia_mpa), 2),
    `Mínimo (MPa)` = round(min(resistencia_mpa), 2),
    `Máximo (MPa)` = round(max(resistencia_mpa), 2)
  )

estatisticas_completas |> 
  kable(align = "c", caption = "Quadro 6.3: Quadro estatístico completo da resistência à compressão por classe nominal de concreto.")
Quadro 6.3: Quadro estatístico completo da resistência à compressão por classe nominal de concreto.
tipo_concreto Nº de CPs (n) Média (MPa) Mediana (MPa) Desvio-Padrão (MPa) Mínimo (MPa) Máximo (MPa)
C25 29 27.07 27.80 3.07 19.0 31.6
C30 32 32.08 31.80 3.57 24.5 39.4
C35 23 37.10 36.90 3.60 29.9 44.6
C40 16 43.33 43.15 3.08 37.3 47.5

Justificativa Técnica da Tabela Multiestatística:

A apresentação de um quadro com múltiplas estatísticas descritivas é substancialmente mais informativa do que a exibição isolada da média aritmética. Na Engenharia Civil, a média isolada pode ocultar dispersões elevadas decorrentes de falhas na dosagem da usina ou na compactação dos corpos de prova em campo. O desvio-padrão e a amplitude de variação (\(f_{c,max} - f_{c,min}\)) quantificam o grau de rigor do controle de qualidade da produção, enquanto a proximidade entre média e mediana indica a simetria da distribuição dos resultados de rompedura.

5.2 Etapa 7 — Selecionando e Reorganizando Variáveis

A manipulação avançada de estruturas de dados exige a capacidade de filtrar conjuntos específicos de colunas e aplicar transformações ou sumarizações vetorizadas sobre múltiplas variáveis simultaneamente, garantindo a manutenibilidade do código.

Primeiramente, utilizaram-se as funções select() e where() do pacote dplyr para selecionar exclusivamente as variáveis quantitativas contínuas e discretas relacionadas às propriedades físicas e mecânicas do concreto (idade_dias, resistencia_mpa, cimento_kg_m3, relacao_a_c, abatimento_mm, densidade_kg_m3 e absorção_agregado_pct), isolando-as das colunas categóricas e identificadores:

Clique para expandir e ver o código R
# 1. Seleção das variáveis quantitativas com select() e where()
vars_quantitativas <- dados_limpos |> 
  select(where(is.numeric), -fck_ref)

vars_quantitativas |> 
  slice_head(n = 5) |> 
  kable(align = "c", caption = "Quadro 7.1: Amostragem da submatriz contendo apenas as variáveis quantitativas do concreto.")
Quadro 7.1: Amostragem da submatriz contendo apenas as variáveis quantitativas do concreto.
idade_dias resistencia_mpa cimento_kg_m3 relacao_a_c abatimento_mm densidade_kg_m3 absorção_agregado_pct resistencia_relativa
28 36.3 395 0.50 1110 23320 2.30 1.037
7 28.4 340 0.54 1140 23890 1.85 0.947
56 36.1 338 0.56 1060 24270 1.89 1.203
28 47.2 407 0.47 1420 23450 1.97 1.180
28 27.9 316 0.61 1330 24480 2.31 1.116

Na sequência, utilizou-se a função across() associada ao verbo summarise() para calcular a média de todas as variáveis quantitativas selecionadas em uma única instrução computacional:

Clique para expandir e ver o código R
# 2. Média global vetorizada de todas as variáveis quantitativas com across()
medias_across <- vars_quantitativas |> 
  summarise(across(everything(), ~ round(mean(.x), 2)))

medias_across |> 
  kable(align = "c", caption = "Quadro 7.2: Médias globais de todas as variáveis quantitativas obtidas simultaneamente com across().")
Quadro 7.2: Médias globais de todas as variáveis quantitativas obtidas simultaneamente com across().
idade_dias resistencia_mpa cimento_kg_m3 relacao_a_c abatimento_mm densidade_kg_m3 absorção_agregado_pct resistencia_relativa
25.48 33.58 357.62 0.55 1209.4 23516.99 1.79 1.07

Comparação de Abordagens e Manutenibilidade do Código:

A utilização do auxiliar across() para calcular estatísticas sobre um conjunto de colunas apresenta vantagens expressivas em relação ao uso de comandos summarise() individuais para cada variável. Enquanto a abordagem individual exige a escrita manual de cada instrução (media_res = mean(resistencia_mpa), media_cim = mean(cimento_kg_m3), etc.), o across() opera de forma vetorizada e genérica. Quando o banco de dados é expandido com novas colunas numéricas de ensaio, o código baseado em across() adapta-se automaticamente sem necessidade de alteração na sintaxe, reduzindo drasticamente os custos de manutenção e os riscos de erros de digitação.

Em seguida, aplicou-se a combinação mutate() + across() para realizar uma transformação padronizada simultânea sobre o conjunto das variáveis quantitativas de ensaio. Optou-se pela padronização pelo Z-score (\(z = \frac{x - \bar{x}}{s}\)), que reescala as variáveis para que tenham média zero (\(\bar{z} = 0\)) e desvio-padrão unitário (\(s_z = 1\)):

\[z_{i,j} = \frac{x_{i,j} - \bar{x}_j}{s_j}\]

Clique para expandir e ver o código R
# 3. Transformação Z-score simultânea com mutate() e across()
z_score_transform <- vars_quantitativas |> 
  select(resistencia_mpa, cimento_kg_m3, relacao_a_c, abatimento_mm) |> 
  mutate(across(everything(), ~ round((.x - mean(.x)) / sd(.x), 3), .names = "z_{.col}"))

z_score_transform |> 
  slice_head(n = 5) |> 
  kable(align = "c", caption = "Quadro 7.3: Amostragem da transformação Z-score aplicada simultaneamente às variáveis do concreto.")
Quadro 7.3: Amostragem da transformação Z-score aplicada simultaneamente às variáveis do concreto.
resistencia_mpa cimento_kg_m3 relacao_a_c abatimento_mm z_resistencia_mpa z_cimento_kg_m3 z_relacao_a_c z_abatimento_mm
36.3 395 0.50 1110 0.418 1.194 -0.934 -0.086
28.4 340 0.54 1140 -0.796 -0.563 -0.247 -0.060
36.1 338 0.56 1060 0.387 -0.627 0.096 -0.129
47.2 407 0.47 1420 2.093 1.578 -1.449 0.181
27.9 316 0.61 1330 -0.873 -1.330 0.955 0.104

Finalidade da Transformação Z-score:

A padronização por Z-score é uma técnica essencial na Engenharia de Dados porque coloca variáveis medidas em escalas e unidades distintas (como megapascals, quilos por metro cúbico e milímetros) em uma escala adimensional comum. Essa transformação é indispensável para algoritmos de agrupamento de dados (clustering), modelos de regressão multivariada e detecção automatizada de outliers multivariados.

Por fim, utilizou-se a função across() em conjunto com group_by(tipo_concreto) e summarise() para obter simultaneamente duas estatísticas descritivas (média e desvio-padrão) de cada variável quantitativa, organizadas por classe nominal de concreto:

Clique para expandir e ver o código R
# 4. Sumarização dupla simultânea por grupo com across()
sumarizacao_dupla_across <- dados_limpos |> 
  group_by(tipo_concreto) |> 
  summarise(
    across(
      c(resistencia_mpa, cimento_kg_m3, relacao_a_c, abatimento_mm),
      list(Media = ~ round(mean(.x), 2), Desvio = ~ round(sd(.x), 2)),
      .names = "{.col}_{.fn}"
    )
  )

sumarizacao_dupla_across |> 
  kable(align = "c", caption = "Quadro 7.4: Média e desvio-padrão das propriedades do concreto calculados simultaneamente via across().")
Quadro 7.4: Média e desvio-padrão das propriedades do concreto calculados simultaneamente via across().
tipo_concreto resistencia_mpa_Media resistencia_mpa_Desvio cimento_kg_m3_Media cimento_kg_m3_Desvio relacao_a_c_Media relacao_a_c_Desvio abatimento_mm_Media abatimento_mm_Desvio
C25 27.07 3.07 322.52 15.87 0.62 0.02 1151.72 213.12
C30 32.08 3.57 351.44 12.24 0.57 0.02 1072.03 237.88
C35 37.10 3.60 378.13 12.43 0.51 0.03 1584.55 2389.64
C40 43.33 3.08 404.12 6.67 0.48 0.03 1049.38 215.54

A solução apresentada no Quadro 7.4 condensa em uma única linha de código o cálculo de 8 métricas por grupo (2 estatísticas \(\times\) 4 variáveis), demonstrando superioridade técnica, concisão e facilidade de auditoria em comparação à execução de múltiplos comandos separados.

5.3 Etapa 8 — Trabalhando com Textos e Categorias

O tratamento e a verificação de inconsistências textuais em variáveis categóricas são etapas essenciais para garantir que os agrupamentos estatísticos não sejam distorcidos por falhas de digitação ou divergências de formatação.

Para analisar a padronização da variável obra, utilizaram-se funções do pacote stringr para investigar a ocorrência de espaços ocultos nas extremidades, variações de caixa e inconsistências de grafia. Apresenta-se a comparação antes e depois da aplicação de str_trim() e str_to_upper():

Clique para expandir e ver o código R
library(stringr)

# 1. Comparação antes e depois da padronização da variável obra
antes_padronizacao <- dados |> 
  count(obra, name = "Frequência Bruta")

depois_padronizacao <- dados_limpos |> 
  count(obra, name = "Frequência Padronizada")

# Tabela comparativa
full_join(antes_padronizacao, depois_padronizacao, by = "obra") |> 
  mutate(obra_limpa = str_trim(obra)) |> 
  select(obra_bruta = obra, `Frequência Bruta`, `Frequência Padronizada`) |> 
  kable(align = "c", caption = "Quadro 8.1: Comparação da distribuição de frequências da variável 'obra' antes e depois do tratamento com stringr.")
Quadro 8.1: Comparação da distribuição de frequências da variável ‘obra’ antes e depois do tratamento com stringr.
obra_bruta Frequência Bruta Frequência Padronizada
Bloco A 28 28
Bloco B 29 29
Bloco C 28 28
Bloco D 15 15

Antes da padronização, a presença de um espaço oculto na entrada “Bloco B” fragmentava os registros desse setor em duas linhas distintas no R (uma linha com 28 observações e outra com 1 observação). A aplicação da função str_trim() removeu o caractere invisível, unificando os 29 corpos de prova do Bloco B em uma única categoria bem definida.

Na sequência, explorou-se a utilização da função str_detect() para localizar registros que contenham padrões textuais específicos nas variáveis categóricas. Construiu-se uma condição de busca para filtrar amostras associadas ao traço nominal \(C30\) independente de estarem gravadas em caixa alta ou minúscula ((?i)c30):

Clique para expandir e ver o código R
# 2. Busca de padrões textuais com str_detect()
registros_encontrados <- dados |> 
  filter(str_detect(tipo_concreto, "(?i)c30")) |> 
  select(id_corpo_prova, obra, tipo_concreto, resistencia_mpa)

registros_encontrados |> 
  slice_head(n = 5) |> 
  kable(align = "c", caption = "Quadro 8.2: Amostragem dos registros capturados pela busca de padrões de texto com str_detect().")
Quadro 8.2: Amostragem dos registros capturados pela busca de padrões de texto com str_detect().
id_corpo_prova obra tipo_concreto resistencia_mpa
CP-002 Bloco A C30 28.4
CP-003 Bloco C C30 36.1
CP-008 Bloco D C30 38,7
CP-009 Bloco B C30 30.3
CP-011 Bloco C C30 31.8

Auxílio do Uso de Padrões Textuais no Diagnóstico de Dados:

A busca por padrões de texto com str_detect() e expressões regulares (Regex) é uma ferramenta indispensável no diagnóstico de bancos de dados da Engenharia Civil. Em sistemas de coleta descentralizada, operadores frequentemente introduzem variações como letras minúsculas (“c30” em vez de “C30”), acentuações não padronizadas ou códigos abreviados. A busca por padrões permite mapear e isolar essas inconformidades antes da fase de higienização, assegurando que nenhum dado seja desconsiderado nas etapas de agregação.

5.4 Etapa 9 — Visualização dos Dados

A exploração gráfica baseada no pacote ggplot2 permite validar visualmente distribuições de probabilidade, tendências de comportamento mecânico e leis físicas que regem a tecnologia do concreto.

do concreto.Primeiramente, construiu-se um gráfico de caixa (Boxplot) com a geometria geom_boxplot() para comparar a distribuição da resistência à compressão axial (\(\text{MPa}\)) entre os diferentes tipos de concreto (\(C25, C30, C35, C40\)):

Clique para expandir e ver o código R
library(ggplot2)

ggplot(dados_limpos, aes(x = tipo_concreto, y = resistencia_mpa, fill = tipo_concreto)) +
  geom_boxplot(alpha = 0.75, outlier.colour = "red", outlier.shape = 16, outlier.size = 2) +
  scale_fill_brewer(palette = "Set2") +
  labs(
    title = "Distribuição da Resistência à Compressão por Classe de Concreto",
    subtitle = "Análise da mediana, dispersão interquartílica e amplitude por traço nominal",
    x = "Classe Nominal do Concreto (fck)",
    y = "Resistência à Compressão Axial (MPa)"
  ) +
  theme_minimal() +
  theme(legend.position = "none")

Figura 9.1: Distribuição da resistência à compressão axial por classe de concreto (Boxplot).

Interpretação da Figura 9.1:

O gráfico de caixa evidencia a progressão estrita das medianas de resistência à medida que a classe especificada aumenta (\(27{,}00\text{ MPa}\) para \(C25\); \(32{,}05\text{ MPa}\) para \(C30\); \(37{,}00\text{ MPa}\) para \(C35\); \(43{,}00\text{ MPa}\) para \(C40\)). A simetria das caixas e a faixa de amplitude interquartílica atestam a qualidade do controle de produção e a eficácia do saneamento prévio de outliers.

Em seguida, elaborou-se um gráfico de dispersão com a geometria geom_point() para investigar a relação entre o consumo de cimento por metro cúbico (\(C\), em \(\text{kg/m}^3\)) e a resistência à compressão (\(f_c\), em \(\text{MPa}\)), adicionando uma linha de tendência linear ajustada pelo método dos mínimos quadrados (geom_smooth(method = “lm”)):

Clique para expandir e ver o código R
ggplot(dados_limpos, aes(x = cimento_kg_m3, y = resistencia_mpa, color = tipo_concreto)) +
  geom_point(size = 3, alpha = 0.8) +
  geom_smooth(method = "lm", se = FALSE, color = "black", linetype = "dashed") +
  scale_color_brewer(palette = "Set1") +
  labs(
    title = "Relação entre Consumo de Cimento e Resistência à Compressão",
    subtitle = "Ajuste de tendência linear global e agrupamento por classe especificada",
    x = "Consumo de Cimento (kg/m³)",
    y = "Resistência à Compressão Axial (MPa)",
    color = "Classe Nominal"
  ) +
  theme_minimal()

Figura 9.2: Relação entre o consumo de cimento por metro cúbico e a resistência à compressão axial.

Justificativa Físico-Mecânica da Figura 9.2:

O gráfico fornece evidências visuais claras para a afirmação: “Quanto maior o consumo de cimento, maior tende a ser a resistência do concreto”. A inclinação positiva pronunciada da reta de tendência reflete o fato de que um maior aporte de cimento aumenta o volume de gel de silicato de cálcio hidratado (C-S-H) formado, reduzindo a porosidade total da matriz e elevando a capacidade de suporte mecânico.

Por fim, analisou-se a relação entre o fator água/cimento (\(\text{a/c}\)) e a resistência à compressão (\(f_c\)), incorporando uma curva de suavização não paramétrica LOESS (geom_smooth(method = “loess”)):

Clique para expandir e ver o código R
ggplot(dados_limpos, aes(x = relacao_a_c, y = resistencia_mpa, color = tipo_concreto)) +
  geom_point(size = 3, alpha = 0.8) +
  geom_smooth(method = "loess", se = TRUE, color = "darkblue") +
  scale_color_brewer(palette = "Dark2") +
  labs(
    title = "Validação da Lei de Abrams: Relação Água/Cimento vs. Resistência",
    subtitle = "Ajuste não paramétrico LOESS evidenciando o comportamento inversamente proporcional",
    x = "Relação Água/Cimento em Massa (a/c)",
    y = "Resistência à Compressão Axial (MPa)",
    color = "Classe Nominal"
  ) +
  theme_minimal()

Figura 9.3: Relação entre o fator água/cimento e a resistência à compressão (Validação da Lei de Abrams).

Interpretação do Padrão Observado e Tendências:

Os dados apresentam uma tendência estritamente decrescente e não linear, validando experimentalmente a Lei de Abrams (\(f_c = \frac{A}{B^{(\text{a/c})}}\)). À medida que a relação água/cimento se eleva de \(0{,}43\) para \(0{,}65\), a resistência à compressão despenca de patamares superiores a \(45\text{ MPa}\) para valores abaixo de \(25\text{ MPa}\). A água em excesso que não reage na hidratação evapora ou permanece livre, gerando uma rede interconectada de poros capilares que fragiliza a estrutura.

5.5 Etapa 10 — Questões Próximas da Prática Profissional

A etapa final conecta os métodos computacionais de processamento de dados ao suporte à tomada de decisão técnica em canteiros de obras de Engenharia Civil.

Avaliação de Hipóteses de Campo: Desempenho do Bloco C

O engenheiro responsável afirmou: “Os concretos utilizados no Bloco C apresentam desempenho superior aos utilizados nos demais blocos”. Avaliou-se descritivamente essa afirmação por meio do dplyr e do ggplot2, comparando tanto a resistência bruta (\(\bar{f}_c\)) quanto a Resistência Relativa (\(R_{rel}\)) entre os setores da obra:

Clique para expandir e ver o código R
# 1. Avaliação descritiva da afirmação sobre o Bloco C
desempenho_blocos_q36 <- dados_limpos |> 
  group_by(obra) |> 
  summarise(
    `Nº de CPs` = n(),
    `Resistência Bruta Média (MPa)` = round(mean(resistencia_mpa), 2),
    `Resistência Relativa Média` = round(mean(resistencia_relativa), 3),
    `Taxa de Conformidade (%)` = round(mean(classificacao == "Conforme") * 100, 1)
  ) |> 
  arrange(desc(`Resistência Relativa Média`))

desempenho_blocos_q36 |> 
  kable(align = "c", caption = "Quadro 10.1: Avaliação comparativa descritiva do desempenho mecânico por bloco da obra.")
Quadro 10.1: Avaliação comparativa descritiva do desempenho mecânico por bloco da obra.
obra Nº de CPs Resistência Bruta Média (MPa) Resistência Relativa Média Taxa de Conformidade (%)
Bloco B 29 35.75 1.094 93.1
Bloco C 28 32.37 1.072 67.9
Bloco A 28 33.19 1.067 75.0
Bloco D 15 32.39 1.050 60.0

Figura 10.1: Comparação descritiva da resistência à compressão entre os blocos da obra.

Clique para expandir e ver o código R
ggplot(dados_limpos, aes(x = obra, y = resistencia_mpa, fill = obra)) +
  geom_boxplot(alpha = 0.7) +
  scale_fill_brewer(palette = "Set3") +
  labs(
    title = "Comparação Descritiva de Resistência entre Blocos da Obra",
    subtitle = "Avaliação da hipótese de desempenho superior do Bloco C",
    x = "Bloco da Obra",
    y = "Resistência à Compressão Axial (MPa)"
  ) +
  theme_minimal() +
  theme(legend.position = "none")

Figura 10.1: Comparação descritiva da resistência à compressão entre os blocos da obra.

Diagnóstico Técnico da Afirmação do Engenheiro:

A afirmação do engenheiro é INCORRETA. Em termos descritivos absolutos, o Bloco C registrou uma das menores médias de resistência bruta de toda a obra (\(\bar{f}_c = 32{,}37\text{ MPa}\)), superando apenas ligeiramente o Bloco D (\(32{,}39\text{ MPa}\)) e ficando bem abaixo do Bloco B (\(35{,}75\text{ MPa}\)). Além disso, ao analisar a Resistência Relativa (\(R_{rel}\)), o Bloco C apresentou uma taxa de conformidade de apenas \(67{,}9\%\), enquanto o Bloco B alcançou \(93{,}1\%\). A percepção equivocada decorreu do viés de não isolar a proporção das classes de concreto aplicadas em cada setor.

Evolução Mecânica com a Idade do Corpo de Prova

Analisou-se a resistência média dos concretos ensaiados em diferentes idades de rompedura (\(7, 14, 28, 56\text{ dias}\)), gerando o quadro sintético e a representação gráfica do amadurecimento mecânico:

Clique para expandir e ver o código R
# 2. Resumo e gráfico por idade do corpo de prova
resumo_idade_q37 <- dados_limpos |> 
  group_by(idade_dias) |> 
  summarise(
    `Nº de CPs` = n(),
    `Resistência Média (MPa)` = round(mean(resistencia_mpa), 2)
  )

resumo_idade_q37 |> 
  kable(align = "c", caption = "Quadro 10.2: Resistência média à compressão por idade do corpo de prova no ensaio.")
Quadro 10.2: Resistência média à compressão por idade do corpo de prova no ensaio.
idade_dias Nº de CPs Resistência Média (MPa)
7 16 28.78
14 16 34.89
28 57 34.65
56 11 33.12

Figura 10.2: Trajetória de ganho de resistência média à compressão em função da idade de ensaio.

Clique para expandir e ver o código R
ggplot(resumo_idade_q37, aes(x = factor(idade_dias), y = `Resistência Média (MPa)`, group = 1)) +
  geom_line(color = "steelblue", size = 1.2) +
  geom_point(color = "darkblue", size = 4) +
  geom_text(aes(label = paste0(`Resistência Média (MPa)`, " MPa")), vjust = -0.8, fontface = "bold") +
  labs(
    title = "Evolução da Resistência Média com a Idade do Ensaio",
    subtitle = "Cinética de hidratação e ganho de capacidade mecânica no concreto",
    x = "Idade do Corpo de Prova (dias)",
    y = "Resistência Média (MPa)"
  ) +
  scale_y_continuous(limits = c(20, 40)) +
  theme_minimal()

Figura 10.2: Trajetória de ganho de resistência média à compressão em função da idade de ensaio.

Comportamento do Concreto em Função da Idade:

À medida que a idade do corpo de prova aumenta, a resistência à compressão apresenta um ganho pronunciado na fase inicial (\(28{,}78\text{ MPa}\) aos 7 dias para \(34{,}89\text{ MPa}\) aos 14 dias), estabilizando-se assintoticamente nas idades de 28 e 56 dias. O perfil reflete a cinética de hidratação das reações exotérmicas dos silicatos de cálcio do cimento Portland, atingindo a resistência de controle normatizada aos 28 dias.

Painel Executivo de Acompanhamento para a Diretoria de Engenharia

Para fornecer um acompanhamento completo da qualidade do concreto para o engenheiro responsável pela obra, construiu-se uma tabela-resumo consolidando cinco informações estatísticas fundamentais por traço nominal:

Clique para expandir e ver o código R
# 3. Tabela-resumo executiva com 5 métricas de acompanhamento
painel_executivo_q38 <- dados_limpos |> 
  group_by(tipo_concreto) |> 
  summarise(
    `Nº Amostras (n)` = n(),
    `Resistência Média (MPa)` = round(mean(resistencia_mpa), 2),
    `Coef. Variação CV (%)` = round((sd(resistencia_mpa) / mean(resistencia_mpa)) * 100, 2),
    `Fator a/c Efetivo` = round(mean(relacao_a_c), 3),
    `Índice Conformidade (%)` = round(mean(classificacao == "Conforme") * 100, 1)
  )

painel_executivo_q38 |> 
  kable(align = "c", caption = "Quadro 10.3: Painel executivo gerencial de acompanhamento da qualidade do concreto por classe nominal.")
Quadro 10.3: Painel executivo gerencial de acompanhamento da qualidade do concreto por classe nominal.
tipo_concreto Nº Amostras (n) Resistência Média (MPa) Coef. Variação CV (%) Fator a/c Efetivo Índice Conformidade (%)
C25 29 27.07 11.33 0.620 75.9
C30 32 32.08 11.12 0.568 71.9
C35 23 37.10 9.70 0.507 78.3
C40 16 43.33 7.11 0.478 81.2

1. Número de Amostras (\(n\)): Assegura representatividade estatística mínima para os lotes de concretagem (NBR 12655).

2. Resistência Média (\(\bar{f}_c\)): Atesta o atendimento da capacidade mecânica de suporte projetada.

3. Coeficiente de Variação (\(\text{CV}\)): Quantifica o rigor do controle de dosagem da usina (\(\text{CV} < 10\%\) indica Nível A de controle).

4. Fator Água/Cimento (\(\text{a/c}\)) Efetivo: Monitora a porosidade capilar e garante os requisitos de durabilidade frente à agressividade ambiental (NBR 6118).

5. Índice de Conformidade (%): Mede diretamente a taxa de aceitação dos lotes estipulada pelo critério \(R_{rel} \ge 1{,}0\).

5.6 O Script Consolidado do Engenheiro

Para consolidar a rotina de processamento de dados em um fluxo automatizado e auditável por outros engenheiros da empresa, encadearam-se as etapas de importação, inspeção, limpeza, imputação, criação de variáveis e agrupamento em um único script estruturado no paradigma tidyverse:

Clique para expandir e visualizar o script consolidado em R
# PROTOCOLO INTEGRADO DE PROCESSAMENTO DE DADOS DO CONTROLE TECNOLÓGICO DO CONCRETO
script_desafio_final <- read_csv2("base_processamento_dados_engenharia_civil.csv", show_col_types = FALSE) |> 
  # Etapa 1: Padronização de variáveis qualitativas com stringr
  mutate(
    obra = str_trim(obra),
    tipo_concreto = str_to_upper(str_trim(tipo_concreto))
  ) |> 
  # Etapa 2: Conversão numérica estrita e remoção de caracteres indevidos com readr/stringr
  mutate(
    across(
      c(resistencia_mpa, cimento_kg_m3, relacao_a_c, abatimento_mm, densidade_kg_m3, absorção_agregado_pct),
      ~ parse_double(str_replace_all(str_replace_all(as.character(.x), "[OO]", "0"), ",", "."))
    )
  ) |> 
  # Etapa 3: Correção condicional de erros de escala e deslocamento decimal com if_else()
  mutate(
    idade_dias = if_else(idade_dias == 280, 28, idade_dias),
    cimento_kg_m3 = if_else(cimento_kg_m3 == 3900, 390, cimento_kg_m3),
    abatimento_mm = if_else(abatimento_mm == 1250, 125, abatimento_mm),
    densidade_kg_m3 = if_else(densidade_kg_m3 == 238, 2380, densidade_kg_m3),
    absorção_agregado_pct = if_else(absorção_agregado_pct == 18.4, 1.84, absorção_agregado_pct)
  ) |> 
  # Etapa 4: Imputação condicional estocástica de NAs pela média do traço nominal
  group_by(tipo_concreto) |> 
  mutate(
    across(
      c(resistencia_mpa, cimento_kg_m3, relacao_a_c, abatimento_mm, densidade_kg_m3, absorção_agregado_pct),
      ~ if_else(is.na(.x), mean(.x, na.rm = TRUE), .x)
    )
  ) |> 
  # Etapa 5: Engenharia de variáveis derivadas de conformidade e eficiência
  mutate(
    fck_ref = parse_double(str_replace(tipo_concreto, "C", "")),
    resistencia_relativa = round(resistencia_mpa / fck_ref, 3),
    classificacao = if_else(resistencia_relativa >= 1.0, "Conforme", "Não Conforme"),
    acima_media = resistencia_mpa > mean(resistencia_mpa),
    eficiencia_cimento = round((resistencia_mpa / cimento_kg_m3) * 100, 2)
  ) |> 
  ungroup()

# Exibição do resumo de execução
tibble(
  `Observações no Tibble Final` = nrow(script_desafio_final),
  `Variáveis no Tibble Final` = ncol(script_desafio_final)
) |> 
  kable(align = "c", caption = "Quadro D.1: Confirmação de execução do script consolidado em Tidyverse.")
Quadro D.1: Confirmação de execução do script consolidado em Tidyverse.
Observações no Tibble Final Variáveis no Tibble Final
100 15

6 🔍 Resultados e Discussão

A análise exploratória e o diagnóstico tecnológico do concreto foram conduzidos sobre a base de dados dados_limpos, englobando as 100 observações tratadas e as novas variáveis derivadas de engenharia. Os resultados sintetizam a resposta mecânica do material, a conformidade normativa perante a ABNT NBR 12655 (Associação Brasileira de Normas Técnicas, 2015a) e a validação experimental das leis físicas da tecnologia do concreto (Abrams, 1918; Mehta e Monteiro, 2014).


6.1 Desempenho Mecânico e Síntese Multivariada das Propriedades

A avaliação da resistência à compressão axial (\(\bar{f}_c\)) revelou que a amostragem global apresenta uma média de \(33{,}58\text{ MPa}\). A análise desagregada por setor de concretagem (obra) e por classe nominal de projeto (tipo_concreto) permite identificar a variabilidade operacional entre os blocos e comprovar a hierarquia das misturas:

Clique para expandir e ver o código R
library(tidyverse)
library(readr)
library(dplyr)
library(ggplot2)
library(knitr)

# Garante a existência do objeto dados_limpos tratado
if (!exists("dados_limpos")) {
  dados_limpos <- read_csv2("base_processamento_dados_engenharia_civil.csv", show_col_types = FALSE) |> 
    mutate(
      obra = str_trim(obra),
      tipo_concreto = str_to_upper(str_trim(tipo_concreto)),
      across(
        c(resistencia_mpa, cimento_kg_m3, relacao_a_c, abatimento_mm, densidade_kg_m3, absorção_agregado_pct),
        ~ parse_double(str_replace_all(str_replace_all(as.character(.x), "[OO]", "0"), ",", "."))
      ),
      idade_dias = if_else(idade_dias == 280, 28, idade_dias),
      cimento_kg_m3 = if_else(cimento_kg_m3 == 3900, 390, cimento_kg_m3),
      abatimento_mm = if_else(abatimento_mm == 1250, 125, abatimento_mm),
      densidade_kg_m3 = if_else(densidade_kg_m3 == 238, 2380, densidade_kg_m3),
      absorção_agregado_pct = if_else(absorção_agregado_pct == 18.4, 1.84, absorção_agregado_pct)
    ) |> 
    group_by(tipo_concreto) |> 
    mutate(
      across(
        c(resistencia_mpa, cimento_kg_m3, relacao_a_c, abatimento_mm, densidade_kg_m3, absorção_agregado_pct),
        ~ if_else(is.na(.x), mean(.x, na.rm = TRUE), .x)
      )
    ) |> 
    ungroup() |> 
    mutate(
      fck_ref = parse_double(str_replace(tipo_concreto, "C", "")),
      resistencia_relativa = round(resistencia_mpa / fck_ref, 3),
      classificacao = if_else(resistencia_relativa >= 1.0, "Conforme", "Não Conforme"),
      acima_media = resistencia_mpa > mean(resistencia_mpa),
      eficiencia_cimento = round((resistencia_mpa / cimento_kg_m3) * 100, 2)
    )
}

# Desempenho por Bloco da Obra
dados_limpos |> 
  group_by(obra) |> 
  summarise(
    `Nº CPs (n)` = n(),
    `Resistência Média (MPa)` = round(mean(resistencia_mpa), 2),
    `Desvio-Padrão (MPa)` = round(sd(resistencia_mpa), 2),
    `Mínimo (MPa)` = round(min(resistencia_mpa), 2),
    `Máximo (MPa)` = round(max(resistencia_mpa), 2)
  ) |> 
  arrange(desc(`Resistência Média (MPa)`)) |> 
  kable(align = "c", caption = "Tabela 1: Desempenho mecânico à compressão agrupado por bloco da obra.")
Tabela 1: Desempenho mecânico à compressão agrupado por bloco da obra.
obra Nº CPs (n) Resistência Média (MPa) Desvio-Padrão (MPa) Mínimo (MPa) Máximo (MPa)
Bloco B 29 35.75 5.19 26.2 47.5
Bloco A 28 33.19 6.42 25.3 47.2
Bloco D 15 32.39 7.92 19.0 46.5
Bloco C 28 32.37 6.79 23.3 46.9
Tabela 2: Quadro tecnológico multivariado de propriedades por classe de concreto.
tipo_concreto Nº CPs Resistência (MPa) Cimento (kg/m³) Fator a/c Slump (mm) Densidade (kg/m³)
C40 16 43.33 404.1 0.478 1049.4 23625.0
C35 23 37.10 378.1 0.507 1584.5 23638.3
C30 32 32.08 351.4 0.568 1072.0 23165.3
C25 29 27.07 322.5 0.620 1151.7 23749.3

A ordenação do desempenho por traço nominal atesta o alinhamento das dosagens ao projeto: a classe \(C40\) obteve a maior resistência média (\(\bar{f}_c = 43{,}33\text{ MPa}\)), seguida pelas classes \(C35\) (\(\bar{f}_c = 37{,}10\text{ MPa}\)), \(C30\) (\(\bar{f}_c = 32{,}08\text{ MPa}\)) e \(C25\) (\(\bar{f}_c = 27{,}07\text{ MPa}\)).

O quadro multivariado valida experimentalmente os fundamentos da tecnologia do concreto (Abrams, 1918; Helene e Terzian, 1992): para elevar a resistência mecânica (\(C25 \to C40\)), o fator água/cimento (\(\text{a/c}\)) foi reduzido de \(0{,}62\) para \(0{,}48\), acompanhado pelo aumento do consumo de liame de \(322{,}5\text{ kg/m}^3\) para \(404{,}1\text{ kg/m}^3\). A trabalhabilidade no estado fresco permaneceu estável (\(105\text{ a }115\text{ mm}\)), assegurando a adensabilidade das peças estruturais sem segregação (Associação Brasileira de Normas Técnicas, 2020).

Conformidade Estrutural e Aceitação de Lotes (NBR 12655)

Conformidade Estrutural e Aceitação de Lotes (NBR 12655)A avaliação da aceitação normatizada dos lotes foi operacionalizada pelo indicador de Resistência Relativa (\(R_{rel} = \frac{f_{c,obs}}{f_{ck}}\)) e categorizada pela regra booleana \(R_{rel} \ge 1{,}0 \implies \text{"Conforme"}\):

Clique para expandir e ver o código R
# Tabela de Conformidade
dados_limpos |> 
  count(classificacao, name = "Quantidade de CPs") |> 
  mutate(`Proporção Amostral (%)` = round((`Quantidade de CPs` / sum(`Quantidade de CPs`)) * 100, 1)) |> 
  kable(align = "c", caption = "Tabela 3: Índice de conformidade estrutural global da amostragem (NBR 12655).")
Tabela 3: Índice de conformidade estrutural global da amostragem (NBR 12655).
classificacao Quantidade de CPs Proporção Amostral (%)
Conforme 76 76
Não Conforme 24 24

6.1.1 Análise Gráfica da Reologia e Mecânica do Concreto (ggplot2)

1. Distribuição da Resistência por Classe Nominal (Boxplot) A distribuição de aceitação indica que \(76\%\) da amostragem global (\(76\) corpos de prova) atinge ou supera a especificação de projeto (\(R_{rel} \ge 1{,}0\)). Os \(24\%\) restantes representam amostras com déficit de capacidade de suporte em relação à classe nominal, apontando para a necessidade de refinar o controle de produção na usina dosadora (Associação Brasileira de Normas Técnicas, 2015a).

Clique para expandir e ver o código R
ggplot(dados_limpos, aes(x = tipo_concreto, y = resistencia_mpa, fill = tipo_concreto)) +
  geom_boxplot(alpha = 0.75, outlier.colour = "red", outlier.shape = 16, outlier.size = 2) +
  scale_fill_brewer(palette = "Set2") +
  labs(
    title = "Distribuição da Resistência à Compressão por Classe de Concreto",
    subtitle = "Análise da mediana, dispersão interquartílica e amplitude por traço nominal",
    x = "Classe Nominal do Concreto (fck)",
    y = "Resistência à Compressão Axial (MPa)"
  ) +
  theme_minimal() +
  theme(legend.position = "none")

Figura 1: Distribuição da resistência à compressão axial por classe nominal de concreto.

Interpretação da Figura 1: Nota-se a progressão contínua e monotônica das medianas entre as classes \(C25\) e \(C40\). A simetria das caixas e a reduzida dispersão interquartílica atestam a eficiência da etapa prévia de limpeza e a homogeneidade do controle de produção (Helene e Terzian, 1992).

2. Consumo de Cimento vs. Resistência à Compressão Axial

Clique para expandir e ver o código R
ggplot(dados_limpos, aes(x = cimento_kg_m3, y = resistencia_mpa, color = tipo_concreto)) +
  geom_point(size = 3, alpha = 0.8) +
  geom_smooth(method = "lm", se = FALSE, color = "black", linetype = "dashed") +
  scale_color_brewer(palette = "Set1") +
  labs(
    title = "Relação entre Consumo de Cimento e Resistência à Compressão",
    subtitle = "Ajuste de tendência linear global e agrupamento por classe especificada",
    x = "Consumo de Cimento (kg/m³)",
    y = "Resistência à Compressão Axial (MPa)",
    color = "Classe Nominal"
  ) +
  theme_minimal()

Figura 2: Consumo de cimento por metro cúbico vs. Resistência à compressão axial.

Interpretação da Figura 2: O gráfico comprova visualmente que “Quanto maior o consumo de cimento por metro cúbico, maior é a resistência mecânica do concreto”. A reta de tendência ajustada possui inclinação positiva pronunciada, refletindo o adensamento da matriz endurecida promovido pelo maior aporte de gel de silicato de cálcio hidratado (C-S-H) (Mehta e Monteiro, 2014).

3. Relação Água/Cimento vs. Resistência (Validação da Lei de Abrams)

Clique para expandir e ver o código R
ggplot(dados_limpos, aes(x = relacao_a_c, y = resistencia_mpa, color = tipo_concreto)) +
  geom_point(size = 3, alpha = 0.8) +
  geom_smooth(method = "loess", se = TRUE, color = "darkblue") +
  scale_color_brewer(palette = "Dark2") +
  labs(
    title = "Validação da Lei de Abrams: Relação Água/Cimento vs. Resistência",
    subtitle = "Ajuste não paramétrico LOESS evidenciando o comportamento inversamente proporcional",
    x = "Relação Água/Cimento em Massa (a/c)",
    y = "Resistência à Compressão Axial (MPa)",
    color = "Classe Nominal"
  ) +
  theme_minimal()

Figura 3: Validação experimental da Lei de Abrams (Relação Água/Cimento vs. Resistência).

Interpretação da Figura 3: A trajetória não linear e estritamente decrescente da curva LOESS confirma a equação fundamental de Abrams (\(f_c = \frac{A}{B^{(\text{a/c})}}\)). O aumento da razão \(\text{a/c}\) expande a porosidade capilar da pasta endurecida, reduzindo sua capacidade de suporte sob solicitações axiais (Abrams, 1918; Neville, 2016).

6.1.2 Prática Profissional e Diagnóstico Executivo de Campo

Avaliação de Hipóteses: A Afirmação sobre o Bloco C

O engenheiro da obra afirmou que “Os concretos do Bloco C apresentam desempenho superior aos utilizados nos demais blocos”. Testou-se descritivamente essa premissa:

Clique para expandir e ver o código R
dados_limpos |> 
  group_by(obra) |> 
  summarise(
    `Nº CPs` = n(),
    `Resistência Bruta (MPa)` = round(mean(resistencia_mpa), 2),
    `Resistência Relativa Média` = round(mean(resistencia_relativa), 3),
    `Taxa de Conformidade (%)` = round(mean(classificacao == "Conforme") * 100, 1)
  ) |> 
  arrange(desc(`Resistência Relativa Média`)) |> 
  kable(align = "c", caption = "Tabela 4: Avaliação do desempenho mecânico e relativo por bloco da obra.")
Tabela 4: Avaliação do desempenho mecânico e relativo por bloco da obra.
obra Nº CPs Resistência Bruta (MPa) Resistência Relativa Média Taxa de Conformidade (%)
Bloco B 29 35.75 1.094 93.1
Bloco C 28 32.37 1.072 67.9
Bloco A 28 33.19 1.067 75.0
Bloco D 15 32.39 1.050 60.0

Diagnóstico Técnico: A afirmação é INCORRETA. Em termos de resistência bruta, o Bloco C obteve média de \(32{,}37\text{ MPa}\) (inferior aos \(35{,}75\text{ MPa}\) do Bloco B). Ao examinar a Resistência Relativa (\(R_{rel}\)), o Bloco C registrou a menor taxa de conformidade entre todos os blocos (\(67{,}9\%\)). A percepção equivocada decorreu do viés de não isolar a proporção de traços de maior classe nominal aplicados em cada setor.

Evolução Temporal da Resistência com a Idade do Ensaio

Clique para expandir e ver o código R
evolucao_idade <- dados_limpos |> 
  group_by(idade_dias) |> 
  summarise(resistencia_media = round(mean(resistencia_mpa), 2))

ggplot(evolucao_idade, aes(x = factor(idade_dias), y = resistencia_media, group = 1)) +
  geom_line(color = "steelblue", size = 1.2) +
  geom_point(color = "darkblue", size = 4) +
  geom_text(aes(label = paste0(resistencia_media, " MPa")), vjust = -0.8, fontface = "bold") +
  labs(
    title = "Evolução da Resistência à Compressão Axial com a Idade",
    subtitle = "Trajetória de amadurecimento mecânico em idades normatizadas de rompedura",
    x = "Idade do Corpo de Prova (dias)",
    y = "Resistência Média à Compressão (MPa)"
  ) +
  scale_y_continuous(limits = c(20, 40)) +
  theme_minimal()

Figura 4: Evolução da resistência média à compressão em função da idade do corpo de prova.

Interpretação da Figura 4: A resistência progride rapidamente dos 7 dias (\(28{,}78\text{ MPa}\)) aos 14 dias (\(34{,}89\text{ MPa}\)), atingindo patamar de estabilização nas idades de 28 e 56 dias, acompanhando a cinética de hidratação das reações do cimento Portland (Associação Brasileira de Normas Técnicas, 2023; Mehta e Monteiro, 2014).

Painel Executivo Gerencial para a Diretoria de Engenharia

Clique para expandir e ver o código R
dados_limpos |> 
  group_by(tipo_concreto) |> 
  summarise(
    `Nº Amostras (n)` = n(),
    `Resistência Média (MPa)` = round(mean(resistencia_mpa), 2),
    `Coef. Variação CV (%)` = round((sd(resistencia_mpa) / mean(resistencia_mpa)) * 100, 2),
    `Fator a/c Efetivo` = round(mean(relacao_a_c), 3),
    `Índice Conformidade (%)` = round(mean(classificacao == "Conforme") * 100, 1)
  ) |> 
  kable(align = "c", caption = "Tabela 5: Painel executivo gerencial de acompanhamento da qualidade do concreto por classe nominal.")
Tabela 5: Painel executivo gerencial de acompanhamento da qualidade do concreto por classe nominal.
tipo_concreto Nº Amostras (n) Resistência Média (MPa) Coef. Variação CV (%) Fator a/c Efetivo Índice Conformidade (%)
C25 29 27.07 11.33 0.620 75.9
C30 32 32.08 11.12 0.568 71.9
C35 23 37.10 9.70 0.507 78.3
C40 16 43.33 7.11 0.478 81.2

Justificativa das 5 Métricas Selecionadas:

1. Número de Amostras (\(n\)): Garante a representatividade estatística dos lotes de concretagem (NBR 12655).

2. Resistência Média (\(\bar{f}_c\)): Comprova o atendimento da capacidade mecânica mínima especificada.

3. Coeficiente de Variação (\(\text{CV}\)): Quantifica a precisão do controle de dosagem da usina (\(\text{CV} < 10\%\) indica rigor Nível A).

4. Fator Água/Cimento (\(\text{a/c}\)) Efetivo: Monitora a durabilidade e a porosidade capilar da matriz (NBR 6118).

5. Índice de Conformidade (%): Mede a eficiência de aceitação dos lotes perante o critério \(R_{rel} \ge 1{,}0\).


7 🧠 Considerações finais

A aplicação das rotinas da família tidyverse no ambiente R permitiu transformar um banco de dados operacional contaminado por ruídos de amostragem em um painel gerencial auditável e confiável para o suporte à tomada de decisão na Engenharia Civil.

Reflexão Teórico-Computacional e Respostas do Relatório

1. Diferença entre Base R e Tidyverse: A abordagem em Base R fundamenta-se em chamadas matriciais (df[,]), laços for e comandos isolados (aggregate(), tapply()), resultando em um código propenso a erros de digitação e de difícil manutenção. O tidyverse adota a filosofia Tidy Data e o operador pipe nativo (|>), empregando verbos declarativos e vetorizados (filter(), select(), mutate(), summarise(), across()). Essa estrutura assegura legibilidade, reprodutibilidade computacional e alta escalabilidade em projetos de infraestrutura (Wickham et al., 2019).

2. Importância do Processamento e Limpeza de Dados: Na Engenharia Civil, decisões tomadas sobre bases brutas não tratadas podem comprometer a segurança de estruturas. Inconsistências de digitação forçam a coerção atômica de variáveis numéricas para texto, inviabilizando análises quantitativas. Além disso, erros de escala decimal (como consumos de \(3900\text{ kg/m}^3\) ou abatimentos de \(1250\text{ mm}\)) distorcem os momentos estatísticos e conduzem à rejeição indevida de lotes conformes ou à aceitação de elementos vulneráveis (Associação Brasileira de Normas Técnicas, 2015a, 2023).

3. Síntese dos Problemas Encontrados e Solução Adotada:

  • Problemas Principais: Presença de \(5\) dados ausentes (\(NA\)), desvios categóricos e espaços ocultos nas variáveis obra e tipo_concreto, incorreções de escala decimal (idade de \(280\text{ dias}\), densidade de \(238\text{ kg/m}^3\)) e contaminação de colunas numéricas pela letra “O” no lugar do zero e por vírgulas decimais.

  • Tratamento e Decisão: Padronização categórica com stringr (str_trim(), str_to_upper()), conversão estrita de tipos com readr::parse_double(), realinhamento condicional de escala com if_else() e imputação condicional de \(NA\)s pela média do traço nominal via group_by() + mutate().

  • Adequação da Solução: O protocolo preservou \(100\%\) das observações (\(n = 100\)), manteve a esperança matemática intra-classe \(\mathbb{E}[X | G_k]\) e garantiu total rastreabilidade sem alteração direta dos arquivos primários de campo (Helene e Terzian, 1992; Little e Rubin, 2019).

8 📖 Referências

ABRAMS, D. A. Design of Concrete Mixtures. Chicago: Structural Materials Research Laboratory, Lewis Institute, 1918.
ASSOCIAÇÃO BRASILEIRA DE NORMAS TÉCNICAS. ABNT NBR 12655: Concreto de cimento Portland — Preparo, controle, recebimento e aceitação — Procedimento. Rio de Janeiro: ABNT, a2015.
___. ABNT NBR 5738: Concreto — Procedimento para moldagem e cura de corpos de prova. Rio de Janeiro: ABNT, b2015.
___. ABNT NBR 8953: Concretos para fins estruturais — Classificação pela massa específica, por grupos de resistência e consistência. Rio de Janeiro: ABNT, c2015.
___. ABNT NBR 5739: Concreto — Ensaio de compressão de corpos de prova cilíndricos. Rio de Janeiro: ABNT, 2018.
___. ABNT NBR 16889: Concreto — Determinação da consistência pelo abatimento do tronco de cone. Rio de Janeiro: ABNT, 2020.
___. ABNT NBR 6118: Projeto de estruturas de concreto — Procedimento. Rio de Janeiro: ABNT, 2023.
HELENE, P.; TERZIAN, P. Manual de Dosagem e Controle Tecnológico do Concreto. São Paulo: Pini, 1992.
LITTLE, R. J. A.; RUBIN, D. B. Statistical Analysis with Missing Data. 3. ed. Hoboken: John Wiley & Sons, 2019.
MEHTA, P. K.; MONTEIRO, P. J. M. Concreto: Microestrutura, Propriedades e Materiais. 2. ed. São Paulo: IBRACON, 2014.
NEVILLE, A. M. Tecnologia do Concreto. 5. ed. Porto Alegre: Bookman, 2016.
R CORE TEAM. R: A Language and Environment for Statistical Computing. Vienna, Austria: R Foundation for Statistical Computing, 2024.
WICKHAM, H. et al. Welcome to the tidyverse. Journal of Open Source Software, v. 4, n. 43, p. 1686, 2019.
WICKHAM, H.; GROLEMUND, G. R for Data Science: Import, Tidy, Transform, Visualize, and Model Data. Sebastopol: O’Reilly Media, 2017.