1 Configuración y Carga de Datos

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


#### VARIABLE LONGITUD ####
## DATASET ##
setwd("~/R/LONGITUD")
# Cargar dataset
Datos <- read.csv("Data_Mundial_Final.csv", sep = ";", dec = ",", fileEncoding = "latin1")
# Estructura de los datos
str(Datos)
## 'data.frame':    58771 obs. of  29 variables:
##  $ OBJECTID              : int  127 129 131 132 133 137 138 139 140 145 ...
##  $ code                  : chr  "00127-ARG-P" "00129-ARG-G" "00131-ARG-P" "00132-ARG-P" ...
##  $ plant_name            : chr  "Aconcagua solar farm" "Altiplano 200 Solar Power Plant" "Anchoris solar farm" "Antu Newen solar farm" ...
##  $ country               : chr  "Argentina" "Argentina" "Argentina" "Argentina" ...
##  $ operational_status    : chr  "announced" "operating" "construction" "cancelled - inferred 4 y" ...
##  $ longitude             : num  -68.9 -66.9 -68.9 -70.3 -66.8 ...
##  $ latitude              : num  -33 -24.1 -33.3 -37.4 -28.6 ...
##  $ elevation             : int  929 4000 937 865 858 570 1612 665 3989 2640 ...
##  $ area                  : num  250 4397290 645 241 30 ...
##  $ size                  : chr  "Small" "Big" "Small" "Small" ...
##  $ slope                 : num  0.574 1.603 0.903 1.791 1.872 ...
##  $ slope_type            : chr  "Plano o casi plano" "Plano o casi plano" "Plano o casi plano" "Plano o casi plano" ...
##  $ curvature             : num  0.000795 -0.002781 0.002781 -0.002384 -0.009137 ...
##  $ curvature_type        : chr  "Superficies planas o intermedias" "Superficies planas o intermedias" "Superficies planas o intermedias" "Superficies planas o intermedias" ...
##  $ aspect                : num  55.1 188.7 108.4 239.3 56.2 ...
##  $ aspect_type           : chr  "Northeast" "South" "East" "Southwest" ...
##  $ dist_to_road          : num  127 56015 336 34 314 ...
##  $ ambient_temperature   : num  12.6 6.8 13.1 11.4 18.8 ...
##  $ ghi                   : num  6.11 8.01 6.12 6.22 6.74 ...
##  $ humidity              : num  53.7 53.7 53.7 53.7 51.5 ...
##  $ wind_speed            : num  3.78 7.02 3.87 6.56 7.19 ...
##  $ wind_direction        : num  55.1 55.1 55.1 55.1 114.8 ...
##  $ dt_wind               : chr  "Northeast" "Northeast" "Northeast" "Northeast" ...
##  $ solar_aptitude        : num  0.746 0.8 0.595 0.657 0.743 ...
##  $ solar_aptitude_rounded: int  7 8 6 7 7 7 8 7 8 6 ...
##  $ solar_aptittude_class : chr  "Alta" "Alta" "Media" "Alta" ...
##  $ capacity              : num  25 101 180 20 50.4 ...
##  $ optimal_tilt          : num  31 26 31 33 30 31 29 31 27 32 ...
##  $ pv_potential          : num  4.98 6.39 4.97 5 5.37 ...
# 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$longitude)
N <- length(Variable)

# CÁLCULO LÍMITES DECIMALES
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

# 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))

# CÁLCULOS MATEMÁTICOS
hi_dec <- (ni_dec / N) * 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)))

# Dataframe Decimal
TDF_Decimal <- data.frame(
  Li = cortes_dec[1:k_dec],
  Ls = cortes_dec[2:(k_dec+1)],
  MC = (cortes_dec[1:k_dec] + cortes_dec[2:(k_dec+1)]) / 2,
  ni = ni_dec,
  hi = hi_dec,
  Ni_asc = Ni_asc_dec,
  Ni_desc = Ni_desc_dec,
  Hi_asc = Hi_asc_dec,
  Hi_desc = Hi_desc_dec)


# CÁLCULO LÍMITES ENTEROS 
BASE <- 10
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

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)]

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 MATEMÁTICOS
hi_int <- (ni_int / N) * 100
Ni_asc_int <- cumsum(ni_int)
Hi_asc_int <- cumsum(hi_int)
Ni_desc_int <- rev(cumsum(rev(ni_int)))
Hi_desc_int <- rev(cumsum(rev(hi_int)))

# 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 = hi_int,
  Ni_asc = Ni_asc_int,
  Ni_desc = Ni_desc_int,
  Hi_asc = Hi_asc_int,
  Hi_desc = Hi_desc_int)

3 Tabla de Distribución de Frecuencias

3.1 Tabla con Límites Decimales

# Crear Dataframe
TDF_Dec_Final <- data.frame(
  Li      = as.character(round(TDF_Decimal$Li, 2)),
  Ls      = as.character(round(TDF_Decimal$Ls, 2)),
  MC      = as.character(round(TDF_Decimal$MC, 2)),
  ni      = as.character(TDF_Decimal$ni),
  hi      = as.character(round(TDF_Decimal$hi, 2)),
  Ni_asc  = as.character(TDF_Decimal$Ni_asc),
  Ni_desc = as.character(TDF_Decimal$Ni_desc),
  Hi_asc  = as.character(round(TDF_Decimal$Hi_asc, 2)),
  Hi_desc = as.character(round(TDF_Decimal$Hi_desc, 2))
)

# Calcular Totales
totales_dec <- c("TOTAL", "-", "-", sum(TDF_Decimal$ni), round(sum(TDF_Decimal$hi), 2), "-", "-", "-", "-")
TDF_Dec_Final <- rbind(TDF_Dec_Final, totales_dec)

# Generar GT
TDF_Dec_Final %>%
 gt() %>%
 tab_header(title = md("**Tabla N°1 de Distribución de Frecuencias de Longitud (°) de las Plantas Solares**")) %>%
 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 (%)"
 ) %>%
 cols_align(align = "center", columns = everything()) %>%
 tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°1 de Distribución de Frecuencias de Longitud (°) de las Plantas Solares
Lim. Inf Lim. Sup Marca Clase Frec. Abs (ni) Frec. Rel (%) Ni (Asc) Ni (Desc) Hi Asc (%) Hi Desc (%)
-124.1 -107.24 -115.67 1592 2.71 1592 58771 2.71 100
-107.24 -90.38 -98.81 1505 2.56 3097 57179 5.27 97.29
-90.38 -73.52 -81.95 4325 7.36 7422 55674 12.63 94.73
-73.52 -56.66 -65.09 1676 2.85 9098 51349 15.48 87.37
-56.66 -39.8 -48.23 1195 2.03 10293 49673 17.51 84.52
-39.8 -22.94 -31.37 220 0.37 10513 48478 17.89 82.49
-22.94 -6.08 -14.51 725 1.23 11238 48258 19.12 82.11
-6.08 10.78 2.35 9820 16.71 21058 47533 35.83 80.88
10.78 27.64 19.21 8569 14.58 29627 37713 50.41 64.17
27.64 44.5 36.07 1374 2.34 31001 29144 52.75 49.59
44.5 61.36 52.93 408 0.69 31409 27770 53.44 47.25
61.36 78.21 69.78 2360 4.02 33769 27362 57.46 46.56
78.21 95.07 86.64 1800 3.06 35569 25002 60.52 42.54
95.07 111.93 103.5 5091 8.66 40660 23202 69.18 39.48
111.93 128.79 120.36 9373 15.95 50033 18111 85.13 30.82
128.79 145.65 137.22 8738 14.87 58771 8738 100 14.87
TOTAL - - 58771 100 - - - -

3.2 Tabla con Límites Enteros

# Crear Dataframe 
TDF_Int_Final <- data.frame(
  Li      = as.character(TDF_Enteros$Li),
  Ls      = as.character(TDF_Enteros$Ls),
  MC      = as.character(TDF_Enteros$MC),
  ni      = as.character(TDF_Enteros$ni),
  hi      = as.character(round(TDF_Enteros$hi, 2)),
  Ni_asc  = as.character(TDF_Enteros$Ni_asc),
  Ni_desc = as.character(TDF_Enteros$Ni_desc),
  Hi_asc  = as.character(round(TDF_Enteros$Hi_asc, 2)),
  Hi_desc = as.character(round(TDF_Enteros$Hi_desc, 2))
)

# Calcular Totales
totales_int <- c("TOTAL", "-", "-", sum(TDF_Enteros$ni), round(sum(TDF_Enteros$hi), 2), "-", "-", "-", "-")
TDF_Int_Final <- rbind(TDF_Int_Final, totales_int)

# Generar GT
TDF_Int_Final %>%
 gt() %>%
 tab_header(title = md("**Tabla N°2 de Distribución de Frecuencias de Longitud (°) de las Plantas Solares**")) %>%
 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 (%)"
 ) %>%
 cols_align(align = "center", columns = everything()) %>%
 tab_options(heading.title.font.size = px(14), column_labels.background.color = "#F0F0F0")
Tabla N°2 de Distribución de Frecuencias de Longitud (°) de las Plantas Solares
Lim. Inf Lim. Sup Marca Clase Frec. Abs (ni) Frec. Rel (%) Ni (Asc) Ni (Desc) Hi Asc (%) Hi Desc (%)
-130 -110 -120 1501 2.55 1501 58771 2.55 100
-110 -90 -100 1645 2.8 3146 57270 5.35 97.45
-90 -70 -80 5525 9.4 8671 55625 14.75 94.65
-70 -50 -60 739 1.26 9410 50100 16.01 85.25
-50 -30 -40 1099 1.87 10509 49361 17.88 83.99
-30 -10 -20 79 0.13 10588 48262 18.02 82.12
-10 10 0 9571 16.29 20159 48183 34.3 81.98
10 30 20 9681 16.47 29840 38612 50.77 65.7
30 50 40 1316 2.24 31156 28931 53.01 49.23
50 70 60 434 0.74 31590 27615 53.75 46.99
70 90 80 3598 6.12 35188 27181 59.87 46.25
90 110 100 4780 8.13 39968 23583 68.01 40.13
110 130 120 10370 17.64 50338 18803 85.65 31.99
130 150 140 8433 14.35 58771 8433 100 14.35
150 170 160 0 0 58771 0 100 0
TOTAL - - 58771 100 - - - -

4 Análisis Gráfico

4.1 Histogramas de Cantidad

par(mar = c(8, 7, 5, 2)) 
barplot(TDF_Enteros$ni, 
        names.arg = TDF_Enteros$MC,
        main = "",,
        xlab = "", 
        ylab = "",
        col = "#FF6961",
        ylim = c(0, max(TDF_Enteros$ni) * 1.2),
        space = 0, 
        las = 2, 
        cex.names = 0.7)
mtext("Cantidad", side = 2, line = 4.5, cex = 1, font = 1)
mtext("Longitud (°)", side = 1, line = 4)

mtext("Gráfica N°1: Distribución de Cantidad de Plantas Solares por Longitud", 
      side = 3, 
      line = 2, 
      adj = 0.5, 
      cex = 0.9, 
      font = 2)

par(mar = c(8, 7, 5, 2))
barplot(TDF_Enteros$ni, 
        main="",
        xlab = "",
        ylab = "",
        names.arg = TDF_Enteros$MC,
        col = "#FF6961",
        ylim = c(0, 58771),
        space = 0,
        cex.names = 0.7,
        las = 2) 
mtext("Cantidad", side = 2, line = 4.5, cex = 1, font = 1)
mtext("Longitud (°)", side = 1, line = 4)

mtext("Gráfica N°2: Distribución de Cantidad de Plantas Solares por Longitud", 
      side = 3, 
      line = 2, 
      adj = 0.5, 
      cex = 0.9, 
      font = 2)

4.2 Histogramas Porcentuales

par(mar = c(8, 5, 5, 2))
bp3 <- barplot(TDF_Enteros$hi, 
        main = "",
        xlab = "",
        ylab = "Porcentaje (%)",
        col = "#FF6961",
        ylim = c(0, max(TDF_Enteros$hi) * 1.3),
        space = 0,
        names.arg = TDF_Enteros$MC,
        cex.names = 0.7,
        las = 2) 
mtext("Longitud (°)", side = 1, line = 4)

mtext("Gráfica N°3: Distribución Porcentual de las Plantas Solares por Longitud", 
      side = 3, 
      line = 2, 
      adj = 0.5, 
      cex = 0.9, 
      font = 2)

text(x = bp3, 
     y = TDF_Enteros$hi, 
     labels = paste0(round(TDF_Enteros$hi, 1), "%"), 
     pos = 3, cex = 0.6, col = "black")

par(mar = c(8, 5, 5, 2))
bp4 <- barplot(TDF_Enteros$hi, 
        main = "",
        xlab = "",
        ylab = "Porcentaje (%)",
        col = "#FF6961",
        space = 0,
        names.arg = TDF_Enteros$MC,
        las = 2,
        cex.names = 0.7,
        ylim = c(0, 100))
mtext("Longitud (°)", side = 1, line = 4)

mtext("Gráfica N°4: Distribución Porcentual de las Plantas Solares por Longitud", 
      side = 3, 
      line = 2, 
      adj = 0.5, 
      cex = 0.9, 
      font = 2)

text(x = bp4, 
     y = TDF_Enteros$hi, 
     labels = paste0(round(TDF_Enteros$hi, 1), "%"), 
     pos = 3, cex = 0.6, col = "black")

4.3 Diagrama de Cajas (Boxplot)

par(mar = c(5, 5, 4, 2))
boxplot(Variable, 
        horizontal = TRUE,
        col = "#FF6961",
        xlab = "Longitud (°)",
        cex.main = 0.9,
        main = "Gráfica N°5: Distribución de la Longitud en las Plantas Solares")

4.4 Ojivas

par(mar = c(5, 5, 7, 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 = "",
     xlab = "Longitud (°)",
     ylab = "Frecuencia Acumulada",
     col = "black",
     pch = 19, 
     xlim = c(min(TDF_Enteros$Li), max(x_asc)), 
     ylim = c(0, sum(TDF_Enteros$ni)))

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

grid()
mtext("Gráfica N°6: Ojivas Ascendentes y Descendentes de la\nDistribución de la Longitud en las Plantas Solares", 
      side = 3, 
      line = 3, 
      adj = 0.5, 
      cex = 0.9, 
      font = 2)

legend("left", 
       legend = c("Ascendente", "Descendente"), 
       col = c("black", "red"), 
       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
Q1 <- quantile(Variable, 0.25)
Q3 <- quantile(Variable, 0.75)
IQR_val <- Q3 - Q1
lim_inf <- Q1 - 1.5 * IQR_val
lim_sup <- Q3 + 1.5 * IQR_val

outliers_data <- Variable[Variable < lim_inf | Variable > lim_sup]
num_outliers <- length(outliers_data)

if(num_outliers > 0){
  rango_outliers <- paste0(num_outliers, " [", round(min(outliers_data), 2), "; ", round(max(outliers_data), 2), "]")
} else {
  rango_outliers <- "0 [Sin Outliers]"
}

tabla_indicadores <- data.frame(
 "Variable" = c("Longitud (°)"),
 "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" = rango_outliers)

# Generar Tabla GT
tabla_conclusiones_gt <- tabla_indicadores %>%
 gt() %>%
 tab_header(title = md("**Tabla N°3 de Conclusiones de Longitud de las Plantas Solares**")) %>%
 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 [Intervalo]"
 ) %>%
 tab_options(
  heading.title.font.size = px(16),
  column_labels.background.color = "#f0f0f0"
 )

tabla_conclusiones_gt
Tabla N°3 de Conclusiones de Longitud de las Plantas Solares
Variable Rango Media (X) Mediana (Me) Moda (Mo) Varianza (V) Desv. Est. (Sd) C.V. (%) Asimetría (As) Curtosis (K) Outliers [Intervalo]
Longitud (°) [-124.1; 145.65] 43.32 26.29 120 5962.337 77.21617 178.25 -0.3906938 -1.017146 0 [Sin Outliers]
Autor: Martin Sarmiento

6 Conclusiones

La variable “Longitud” fluctúa entre -124.1° y 145.65° y sus valores se encuentran alrededor de 26.29°, con una desviación estándar de 77.21617, siendo una variable muy heterogénea, cuyos valores se concentran en la parte media alta de la variable con la agregación de sin presencia de valores atípicos; por todo lo anterior, el comportamiento de la variable es perjudicial.