1 Configuración y Carga de Datos

##### UNIVERSIDAD CENTRAL DEL ECUADOR #####
#### AUTOR: MARTIN SARMIENTO ####
### CARRERA: INGENIERÍA EN PETRÓLEOS #####


#### VARIABLE AREA ####
## DATASET ##
setwd("~/R/AREA")
# Cargar dataset
Datos <- read.csv("DataSet_.csv", sep = ";", fileEncoding = "latin1")
# Estructura de los datos
str(Datos)
## 'data.frame':    7142 obs. of  26 variables:
##  $ fid                  : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ objectid             : int  127 128 129 130 131 132 133 134 135 136 ...
##  $ code                 : chr  "Arg-00001" "Arg-00002" "Arg-00003" "Arg-00004" ...
##  $ country              : chr  "Argentina" "Argentina" "Argentina" "Argentina" ...
##  $ plant_name           : chr  "Aconcagua solar farm" "Aconcagua solar farm" "Altiplano 200 Solar Power Plant" "Altiplano 200 Solar Power Plant" ...
##  $ operational_status   : chr  "announced" "announced" "operating" "operating" ...
##  $ longitude            : num  -68.9 -68.9 -66.9 -66.9 -68.9 ...
##  $ latitude             : num  -33 -33 -24.1 -24.1 -33.3 ...
##  $ elevation            : int  929 929 4000 4000 937 865 858 858 858 858 ...
##  $ area                 : num  0 0 4397290 5774 0 ...
##  $ slope                : num  0.574 0.574 1.603 6.243 0.903 ...
##  $ slope_type           : chr  "Plano o casi plano" "Plano o casi plano" "Plano o casi plano" "Moderado" ...
##  $ curvature            : num  0.000795 0.000795 -0.002781 -0.043699 0.002781 ...
##  $ curvature_type       : chr  "Superficies planas o intermedias" "Superficies planas o intermedias" "Superficies planas o intermedias" "Superficies cóncavas / Valles" ...
##  $ aspect               : num  55.1 55.1 188.7 270.9 108.4 ...
##  $ aspect_type          : chr  "Northeast" "Northeast" "South" "West" ...
##  $ ghi                  : num  6.11 6.11 8.01 7.88 6.12 ...
##  $ solar_aptitude       : num  0.746 0.746 0.8 0.727 0.595 ...
##  $ solar_aptittude_class: chr  "Alta" "Alta" "Alta" "Alta" ...
##  $ humidity             : num  0 0 53.7 53.7 0 ...
##  $ wind_speed           : num  3.78 3.78 7.02 8.33 3.87 ...
##  $ wind_direction       : num  0 0 55.1 55.1 0 ...
##  $ ambient_temperature  : num  12.6 12.6 6.8 6.8 13.1 ...
##  $ optimal_tilt         : int  31 31 26 26 31 33 30 30 30 30 ...
##  $ peak_power_per_hour  : num  4.98 4.98 6.39 6.39 4.97 ...
##  $ total_power          : num  25 66.2 101 107 180 ...
# Cargamos las librerias
library(dplyr)
## 
## Adjuntando el paquete: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(gt)
library(e1071)

2 Cálculo de Intervalos y Frecuencias

#Extraer variable
Variable <- na.omit(Datos$area)
N <- length(Variable)

# Cálculo Límites Decimales #
# Cálculos básicos
min_dec <- min(Variable)
max_dec <- max(Variable)
k_dec <- floor(1 + 3.322 * log10(N))
rango_dec <- max(Variable) - min(Variable)
amplitud_dec <- rango_dec / k_dec

# Generamos los cortes exactos
cortes_dec <- seq(min(Variable), max(Variable), length.out = k_dec + 1)
cortes_dec[length(cortes_dec)] <- max(Variable) + 0.0001

# Frecuencias
inter_dec <- cut(Variable, breaks = cortes_dec, include.lowest = TRUE, right = FALSE)
ni_dec <- as.vector(table(inter_dec))
hi_dec <- (ni_dec/N)*100

# Cálculos de Frecuencias
sum_ni <- sum(ni_dec)
hi_dec <- (ni_dec / sum_ni) * 100
Ni_asc_dec <- cumsum(ni_dec)
Hi_asc_dec <- cumsum(hi_dec)
Ni_desc_dec <- rev(cumsum(rev(ni_dec)))
Hi_desc_dec <- rev(cumsum(rev(hi_dec)))

# Construcción del Dataframe Decimal
TDF_Decimal <- data.frame(
 Li = round(cortes_dec[1:k_dec], 2),
 Ls = round(cortes_dec[2:(k_dec+1)], 2),
 MC = round((cortes_dec[1:k_dec] + cortes_dec[2:(k_dec+1)]) / 2, 2),
 ni = ni_dec,
 hi = round(hi_dec, 2),
 Ni_asc = cumsum(ni_dec),
 Ni_desc = rev(cumsum(rev(ni_dec))),
 Hi_asc = cumsum(round(hi_dec, 2)),
 Hi_desc = rev(cumsum(rev(round(hi_dec, 2)))))


# Cálculo Límites Enteros #
BASE <- 10

# Cálculos básicos
min_int <- floor(min(Variable) / BASE) * BASE
max_int <- ceiling(max(Variable) / BASE) * BASE
k_int_sug <- floor(1 + 3.322 * log10(N))
Rango_int <- max_int - min_int
Amplitud_raw <- Rango_int / k_int_sug

Amplitud_int <- ceiling(Amplitud_raw / 10) * 10
if(Amplitud_int == 0) Amplitud_int <- 10

# Generar cortes enteros
cortes_int <- seq(from = min_int, by = Amplitud_int, length.out = k_int_sug + 2)

cortes_int <- cortes_int[cortes_int <= (max_int + Amplitud_int)]

# Asegurar cobertura del máximo
while(max(cortes_int) < max(Variable)) {
 cortes_int <- c(cortes_int, max(cortes_int) + Amplitud_int)
}

K_real <- length(cortes_int) - 1
lim_inf_int <- cortes_int[1:K_real]
lim_sup_int <- cortes_int[2:(K_real+1)]

# Frecuencias
inter_int <- cut(Variable, breaks = cortes_int, include.lowest = TRUE, right = FALSE)
ni_int <- as.vector(table(inter_int))

# Cálculos de Frecuencias
hi_int <- (ni_int / N) * 100
Ni_asc_int <- cumsum(ni_int)
Ni_desc_int <- rev(cumsum(rev(ni_int)))
Hi_asc_int <- cumsum(hi_int)
Hi_desc_int <- rev(cumsum(rev(hi_int)))

# Construcción del Dataframe Entero
TDF_Enteros <- data.frame(
 Li = lim_inf_int,
 Ls = lim_sup_int,
 MC = (lim_inf_int + lim_sup_int) / 2,
 ni = ni_int,
 hi = round(hi_int, 2),
 Ni_asc = Ni_asc_int,
 Ni_desc = Ni_desc_int,
 Hi_asc = round(Hi_asc_int, 2),
 Hi_desc = round(Hi_desc_int, 2))

3 Tabla de Distribución de Frecuencias

3.1 Tabla con Límites Decimales

#### Crear de fila de totales ####
totales_dec <- c("TOTAL", "-", "-", sum(TDF_Decimal$ni), 100, "-", "-", "-", "-")
TDF_Dec_Final <- rbind(mutate(TDF_Decimal, across(everything(), as.character)), totales_dec)

# Generar GT Decimal
TDF_Dec_Final %>%
 gt() %>%
 tab_header(title = md("**Tabla N°1 de Distribución de Frecuencias del Área (m²)**")) %>%
 cols_label(
  Li = "Lim. Inf",
  Ls = "Lim. Sup",
  MC = "Marca Clase",
  ni = "Frec. Abs (ni)",
  hi = "Frec. Rel (%)",
  Ni_asc = "Ni (Asc)",
  Ni_desc = "Ni (Desc)",
  Hi_asc = "Hi Asc (%)",
  Hi_desc = "Hi Desc (%)"
 ) %>%
 tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°1 de Distribución de Frecuencias del Área (m²)
Lim. Inf Lim. Sup Marca Clase Frec. Abs (ni) Frec. Rel (%) Ni (Asc) Ni (Desc) Hi Asc (%) Hi Desc (%)
0 1311615.38 655807.69 7044 98.64 7044 7141 98.64 100
1311615.38 2623230.77 1967423.08 27 0.38 7071 97 99.02 1.36
2623230.77 3934846.15 3279038.46 20 0.28 7091 70 99.3 0.98
3934846.15 5246461.54 4590653.85 20 0.28 7111 50 99.58 0.7
5246461.54 6558076.92 5902269.23 10 0.14 7121 30 99.72 0.42
6558076.92 7869692.31 7213884.62 8 0.11 7129 20 99.83 0.28
7869692.31 9181307.69 8525500 0 0 7129 12 99.83 0.17
9181307.69 10492923.08 9837115.38 9 0.13 7138 12 99.96 0.17
10492923.08 11804538.46 11148730.77 2 0.03 7140 3 99.99 0.04
11804538.46 13116153.85 12460346.15 0 0 7140 1 99.99 0.01
13116153.85 14427769.23 13771961.54 0 0 7140 1 99.99 0.01
14427769.23 15739384.62 15083576.92 0 0 7140 1 99.99 0.01
15739384.62 17051000 16395192.31 1 0.01 7141 1 100 0.01
TOTAL - - 7141 100 - - - -

3.2 Tabla con Límites Enteros

#### Crear de fila de totales ####
totales_int <- c("TOTAL", "-", "-", sum(TDF_Enteros$ni), 100, "-", "-", "-", "-")
TDF_Int_Final <- rbind(mutate(TDF_Enteros, across(everything(), as.character)), totales_int)

# Generar GT Enteros
TDF_Int_Final %>%
 gt() %>%
 tab_header(
  title = md("**Tabla N°2 de Distribución de Frecuencias del Área (m²)**")) %>%
 cols_label(
  Li = "Lim. Inf",
  Ls = "Lim. Sup",
  MC = "Marca Clase",
  ni = "Frec. Abs (ni)",
  hi = "Frec. Rel (%)",
  Ni_asc = "Ni (Asc)",
  Ni_desc = "Ni (Desc)",
  Hi_asc = "Hi Asc (%)",
  Hi_desc = "Hi Desc (%)"
 ) %>%

 fmt_number(columns = c(Li, Ls), decimals = 0) %>%
 fmt_number(columns = c(hi, Hi_asc, Hi_desc), decimals = 2) %>%
 tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°2 de Distribución de Frecuencias del Área (m²)
Lim. Inf Lim. Sup Marca Clase Frec. Abs (ni) Frec. Rel (%) Ni (Asc) Ni (Desc) Hi Asc (%) Hi Desc (%)
0 1311620 655810 7044 98.64 7044 7141 98.64 100
1311620 2623240 1967430 27 0.38 7071 97 99.02 1.36
2623240 3934860 3279050 20 0.28 7091 70 99.3 0.98
3934860 5246480 4590670 20 0.28 7111 50 99.58 0.7
5246480 6558100 5902290 10 0.14 7121 30 99.72 0.42
6558100 7869720 7213910 8 0.11 7129 20 99.83 0.28
7869720 9181340 8525530 0 0 7129 12 99.83 0.17
9181340 10492960 9837150 9 0.13 7138 12 99.96 0.17
10492960 11804580 11148770 2 0.03 7140 3 99.99 0.04
11804580 13116200 12460390 0 0 7140 1 99.99 0.01
13116200 14427820 13772010 0 0 7140 1 99.99 0.01
14427820 15739440 15083630 0 0 7140 1 99.99 0.01
15739440 17051060 16395250 1 0.01 7141 1 100 0.01
TOTAL - - 7141 100 - - - -

4 Gráficos

4.1 Gráfico 1 – Frecuencia Local

color_sutil <- "#E3E0AC"

par(mar = c(8, 5, 4, 2)) 
barplot(TDF_Enteros$ni, 
        names.arg = TDF_Enteros$MC,
        main = "Gráfica N°1: Distribución de Cantidad de Plantas Solares por el Área",
        cex.main = 1,
        xlab = "", 
        ylab = "Cantidad",
        col = color_sutil,
        space = 0, 
        las = 2, 
        cex.names = 0.7)
mtext("Área (m²)", side = 1, line = 6)

4.2 Gráfico 2 – Frecuencia Global

color_sutil <- "#E3E0AC"

par(mar = c(8, 5, 4, 2))
barplot(TDF_Enteros$ni, 
        main="Gráfica N°2: Distribución de Cantidades Globales de las Plantas Solares por el Área",
        cex.main = 0.9,
        xlab = "",
        ylab = "Cantidad",
        names.arg = TDF_Enteros$MC,
        col = color_sutil,
        space = 0,
        cex.names = 0.7,
        las = 2,
        ylim = c(0, sum(TDF_Enteros$ni))) 
mtext("Área (m²)", side = 1, line = 6)

4.3 Gráfico 3 – Porcentaje Local

color_sutil <- "#E3E0AC"

par(mar = c(8, 5, 4, 2))
barplot(TDF_Enteros$hi, 
        main="Gráfica N°3: Distribución Porcentual de las Plantas Solares por el Área",
        cex.main = 1,
        xlab = "",
        ylab = "Porcentaje (%)",
        col = color_sutil,
        space = 0,
        names.arg = TDF_Enteros$MC,
        cex.names = 0.7,
        las = 2,
        ylim = c(0, max(TDF_Enteros$hi) * 1.1))
mtext("Área (m²)", side = 1, line = 6)

4.4 Gráfico 4 – Porcentaje Global

color_sutil <- "#E3E0AC"

par(mar = c(8, 5, 4, 2))
barplot(TDF_Enteros$hi, 
        main="Gráfica N°4: Distribución Porcentual Global de las Plantas Solares por el Área",
        cex.main = 1,
        xlab = "",
        ylab = "Porcentaje (%)",
        col = color_sutil,
        space = 0,
        names.arg = TDF_Enteros$MC,
        las = 2,
        cex.names = 0.7,
        ylim = c(0, 100)) 
mtext("Área (m²)", side = 1, line = 6)

4.5 Gráfico 5 – Diagrama de Cajas (Boxplot)

par(mar = c(5, 5, 4, 2))
boxplot(Variable, 
        horizontal = TRUE,
        col = color_sutil,
        xlab = "Área (m²)",
        cex.main = 0.9,
         main = "Gráfica N°5: Distribución del Área en las Plantas Solares")

4.6 Gráfico 6 – Ojivas de Frecuencia Acumulada

par(mar = c(5, 5, 4, 10), xpd = TRUE)

# Coordenadas
x_asc <- TDF_Enteros$Ls
x_desc <- TDF_Enteros$Li
y_asc <- TDF_Enteros$Ni_asc
y_desc <- TDF_Enteros$Ni_desc

# 1. Dibujar la Ascendente 
plot(x_asc, y_asc,
     type = "b", 
     main = "Gráfica N°6: Ojivas Ascendentes y Descendentes de la Distribución del Área en las Plantas Solares",
     cex.main = 0.7,
     xlab = "Área (m²)",
     ylab = "Frecuencia acumulada",
     col = "black",
     pch = 19, 
     xlim = c(min(x_desc), max(x_asc)), 
     ylim = c(0, sum(TDF_Enteros$ni)),
     bty = "l"
)

# 2. Agregar la Descendente 
lines(x_desc, y_desc, col = "#BDB76B", type = "b", pch = 19)

grid()
legend("right", 
       legend = c("Ascendente", "Descendente"), 
       col = c("black", "#BDB76B"), 
       lty = 1, 
       pch = 1, 
       cex = 0.6, 
       inset = c(0.05, 0.05),
       bty = "n")

5 Indicadores Estadísticos

## INDICADORES DE TENDENCIA CENTRAL
# Media aritmética
media <- round(mean(Variable), 2)

# Mediana
mediana <- round(median(Variable), 2)

# Moda
max_frecuencia <- max(TDF_Enteros$ni)
moda_vals <- TDF_Enteros$MC[TDF_Enteros$ni == max_frecuencia]
moda_txt <- paste(round(moda_vals, 2), collapse = ", ")

## INDICADORES DE DISPERSIÓN
# Varianza
varianza <- var(Variable)

# Desviación Estándar
sd_val <- sd(Variable)

# Coeficiente de Variación
cv <- round((sd_val / abs(media)) * 100, 2)

## INDICADORES DE FORMA
# Coeficiente de Asimetría
asimetria <- skewness(Variable, type = 2)

# Curtosis
curtosis <- kurtosis(Variable)

# Outliers
outliers_data <- boxplot.stats(Variable)$out

if(length(outliers_data) > 0) {
 num_out <- length(outliers_data)
 min_out <- round(min(outliers_data), 2)
 max_out <- round(max(outliers_data), 2)

 # Formato Total [Min; Max]
 msg_atipicos <- paste0(" ", num_out, " [", min_out, " ; ", max_out, "]")
} else {
 msg_atipicos <- "No hay presencia de valores atípicos"
}


tabla_indicadores <- data.frame(
 "Variable" = c("Área (m²)"),
 "Rango_MinMax" = paste0("[", round(min(Variable), 2), "; ", round(max(Variable), 2), "]"),
 "X" = c(media),
 "Me" = c(mediana),
 "Mo" = c(moda_txt),
 "V" = c(varianza),
 "Sd" = c(sd_val),
 "Cv" = c(cv),
 "As" = c(asimetria),
 "K" = c(curtosis),
 "Outliers" = msg_atipicos
)

# Generar Tabla GT
tabla_conclusiones_gt <- tabla_indicadores %>%
 gt() %>%
 tab_header(title = md("**Tabla N°3 de Conclusiones**")) %>%
 tab_source_note(source_note = "Autor: Martin Sarmiento") %>%
 cols_label(
  Variable = "Variable",
  Rango_MinMax = "Rango",
  X = "Media (X)",
  Me = "Mediana (Me)",
  Mo = "Moda (Mo)",
  V = "Varianza (V)",
  Sd = "Desv. Est. (Sd)",
  Cv = "C.V. (%)",
  As = "Asimetría (As)",
  K = "Curtosis (K)",
  Outliers = "Outliers"
 ) %>%
 tab_options(
  heading.title.font.size = px(16),
  column_labels.background.color = "#f0f0f0"
 )

tabla_conclusiones_gt
Tabla N°3 de Conclusiones
Variable Rango Media (X) Mediana (Me) Moda (Mo) Varianza (V) Desv. Est. (Sd) C.V. (%) Asimetría (As) Curtosis (K) Outliers
Área (m²) [0; 17051000] 75491.56 0 655810 4.04474e+11 635982.7 842.46 12.53835 193.9159 863 [1.21 ; 17051000]
Autor: Martin Sarmiento

6 Conclusiones

La variable “Área” fluctúa entre 0 y 17051000 m² y sus valores se encuentran alrededor de 0 m², con una desviación estándar de 635982.7, siendo una variable muy heterogénea, cuyos valores se concentran en la parte media baja de la variable con la agregación de presencia de valores atípicos de 863 outliers; por todo lo anterior, el comportamiento de la variable es muy perjudicial.