Antes de iniciar la ejecucion es necesario conocer el formato de nuestro archivo .csv¶
In [ ]:
#Es necesario conocer en que formato se encuentra nuestro archivo
!file -i /content/PSA_2015_2023.csv
Se genera la conexión con Google Drive, se genera la lectura del archivo .csv y se crea un Dataframe.¶
In [ ]:
import pandas as pd
from google.colab import drive
# Lectura en Drive
drive.mount('/content/drive')
# Crear un df con el archivo
df = pd.read_csv('/content/PSA_2015_2023.csv', delimiter=";", encoding='ISO-8859-1')
df.head()
Se crea una copia del dataframe original¶
In [3]:
#Creacion de una copia del data frame (df)
df1 = df
Se realiza la consulta del nombre de las columnas del df¶
In [ ]:
#Para conocer el nombre de las columnas
print(df1.columns.tolist())
Al realizar la consulta de los nombres de las columnas, se logra determinar que existen columnas sin referencia, las cuales procedemos a eliminar del df1¶
In [ ]:
# Eliminar las columnas 'B' y 'C' en el rango
df1.drop(columns=['Unnamed: 38', 'Unnamed: 39', 'Unnamed: 40', 'Unnamed: 41', 'Unnamed: 42', 'Unnamed: 43', 'Unnamed: 44', 'Unnamed: 45', 'Unnamed: 46'], inplace=True)
df1.head()
Se realiza la carga de la blibliotecas y la instalación del modulo para generar el informe.¶
In [ ]:
#Se cargan las librerías necesarias para generar el reporte
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
%pip install ydata_profiling
from ydata_profiling import ProfileReport
Se genera el informe correspondiente al df1¶
In [ ]:
# Creamos el informe con pandas-profiling
nombre = "PSA 2015-2023"
profile = ProfileReport(df1, title=nombre, explorative=True)
# Mostrar el informe en un notebook (si estás usando Jupyter o similares)
profile.to_notebook_iframe()
Se realiza la estimación de los valores Nan (nulos) en el df1¶
In [ ]:
#Se estiman los valores nulos en el Dataframe original
df1.isna().sum()
Se realiza la creación de una columna para generar una contabilización y se modifican los valores "Nan" por valores de 0¶
In [ ]:
# Se crear un diccionario con el nombre y el valor de la columna
new_column_data = {"valor": 1}
# Se llenan valores nulos con 0 y crea la columna "valor" con valor 1
df1_filled = df1.fillna("0").assign(**new_column_data)
print (df1_filled.isna().sum())
print ()
print (df1_filled.head())
** Procedimiento Opcional: **¶
- Se puede asignar un valor de 0 a las filas que contengan valores Nan
- Se puede crear una nueva columna y asignarle valores de 1 para realizar la contabilización.
In [ ]:
#Se asigna un valor de 0 a todas las filas con valores nulos.
#df1_filled = df1.fillna ("0")
#df1_filled.isna().sum()
In [ ]:
#Se agrego una columna nueva ("valor") y se le asigno valores de "1" para poder realizar la contabilización de la cantidad de contratos por Actividad según Provincia
# Drop the existing "valor" column
#df1_filled.drop(columns=["valor"], inplace=True)
#df1_filled.insert(38, "valor", 1)
#print (df1_filled.head())
Se realiza la visualización de los cantidad de contratos por Provincia y Actividad¶
In [ ]:
#Se agrupan la cantidad de contratos por Provincia y Actividad
df1_filled_grouped = df1_filled.groupby(['Provincia', 'Actividad'])['valor'].sum()
df1_filled_grouped
Se grafica la variables Actividad por Provincia y se comprueba los valores de 0¶
In [ ]:
#Para que muestre el codigo se debera de indicar esta linea antes del codigo
%matplotlib inline
# Tamaño del gráfico
plt.figure(figsize=(6, 6))
# Agrupar datos por especie y obtener el promedio
conteo =df1_filled.groupby('Provincia')['valor'].sum()
# Crear gráfico de barras
# sepal_mean.plot(kind='bar')
conteo.plot(kind='barh' )
# Título del gráfico
plt.title('Conteo de Contratos por Provincia')
# Etiqueta del eje Y
plt.ylabel('Provincia')
# Etiqueta del eje X
plt.xlabel('Conteo de contratos')
plt.grid()
plt.show()
Se identifican las filas que presentan valores de Provincia 0¶
In [ ]:
# Filtrar las filas donde la columna "Provincia" es igual a "0"
specific_rows = df1_filled.loc[df1_filled['Provincia'] == '0']
print(specific_rows)
Se realiza la correccion de las filas que poseen valores 0 y se les asigna la Provincia¶
In [13]:
#Se corrigen las columnas que no poseen asignado la Provincia y el valor era 0
df1_filled.loc[(df1_filled['Provincia'] == "0") & (df1_filled['Contrato'] == 'NI-01-204-0279-2015'), 'Provincia'] = 'GUANACASTE'
df1_filled.loc[(df1_filled['Provincia'] == "0") & (df1_filled['Contrato'] == 'SJ-02-22 -0209-2016'), 'Provincia'] = 'SAN JOSÉ'
df1_filled.loc[(df1_filled['Provincia'] == "0") & (df1_filled['Contrato'] == 'SJ-01-22 -0041-2017'), 'Provincia'] = 'ALAJUELA'
df1_filled.loc[(df1_filled['Provincia'] == "0") & (df1_filled['Contrato'] == 'SJ-01-22 -0090-2017'), 'Provincia'] = 'ALAJUELA'
df1_filled.loc[(df1_filled['Provincia'] == "0") & (df1_filled['Contrato'] == 'CN-01-22 -0016-2020'), 'Provincia'] = 'HEREDIA'
df1_filled.loc[(df1_filled['Provincia'] == "0") & (df1_filled['Contrato'] == 'LM-01-222-0049-2020'), 'Provincia'] = 'LIMÓN'
df1_filled.loc[(df1_filled['Provincia'] == "0") & (df1_filled['Contrato'] == 'SJ-01-222-0132-2022'), 'Provincia'] = 'ALAJUELA'
Se realiza la comprobación en la eliminación de los valores 0 en la columna Provincia¶
In [ ]:
# Se comprueba la correccion de la colunma "Provincia" es igual a "0"
specific_rows = df1_filled.loc[df1_filled['Provincia'] == '0']
print(specific_rows)
Se realiza un nuevo plot de las variables Actividad por Provincia, con la correccion generada anteriormente.¶
In [ ]:
# Se imprime nuevamente el gráfico con la corrección realizada.
#Para que muestre el codigo se debera de indicar esta linea antes del codigo en visual studio code
%matplotlib inline
# Tamaño del gráfico
plt.figure(figsize=(6, 6))
# Agrupar datos por especie y obtener el promedio
conteo =df1_filled.groupby('Provincia')['valor'].sum()
# Crear gráfico de barras
# sepal_mean.plot(kind='bar')
conteo.plot(kind='barh' )
# Título del gráfico
plt.title('Conteo de Contratos por Provincia')
# Etiqueta del eje Y
plt.ylabel('Provincia')
# Etiqueta del eje X
plt.xlabel('Conteo de contratos')
plt.grid()
plt.show()
Se realiza la cargar del GeoJSON de las Provincias de CR y se plotea¶
In [ ]:
# Carga los datos geoespaciales de la Provincias de Costa Rica "ProvinciasCR_WGS84.geojson"
import geopandas as gpd
# Se Carga la capa de Provincias de Costa Rica
ruta_archivo = "/content/ProvinciasCR_WGS84.geojson"
gdf = gpd.read_file(ruta_archivo)
# Crea una figura y ejes
fig, ax = plt.subplots()
# Dibuja las geometrías del GeoJSON
gdf.plot(ax=ax, alpha=1, color='blue', figsize= (8,8), edgecolor = 'black', label='GeoJSON')
# Muestra el gráfico
plt.show()
Se realiza la carga del archivo shape de los contratos PSA 2019 y se consulta del tipo de geometría, proyección y datum del shapefile.¶
In [ ]:
# Se lee el archivo y acceso a los detalles de geometria, proyección y datum
ruta_archivo = "/content/PSA_2019_WGS84.shp"
gdf = gpd.read_file(ruta_archivo)
# Se accede a al tipo de geometria y atributos del GeoDataFrame
gdf.geometry
gdf.crs
In [ ]:
# Se carga el shapefile de los proyectos PSA 2019 desde Google Drive.
import geopandas as gpd
gdf = gpd.read_file('/content/PSA_2019_WGS84.shp')
gdf.head()
Se realiza la transformación de de la geometria multipoligono a puntos del shapefile PSA 2019.¶
In [ ]:
import geopandas as gpd
# Lee el shapefile
gdf = gpd.read_file("/content/PSA_2019_WGS84.shp")
# Convierte las geometrías a puntos
gdf['geometry'] = gdf['geometry'].centroid
# Guarda el resultado en un nuevo shapefile
gdf.to_file('puntos_shapefile.shp')
# Se consulta los valores
gdf.head()
Se realiza el plot de los proyectos PSA 2019¶
In [ ]:
gdf_puntos = gpd.read_file('puntos_shapefile.shp')
gdf_puntos.plot()
Al realizar la transformación de la geometría multipoligono a puntos del shapefile PSA 2019, se genera un UserWarning. Motivo por el cual, se realiza el siguiente paso para reproyectar y verificar si efectivamente existe una mala proyección en el archivo de puntos.¶
In [ ]:
regiones = gpd.read_file('puntos_shapefile.shp')
# Ploteo del archivo "puntos_shapefile" con sus coordenadas originales
fig = plt.figure()
ax = fig.add_subplot(111)
regiones.plot(ax=ax, fc='none',ec='black')
plt.title('Regiones de Costa Rica ' + str(regiones.crs))
ax.set_xlabel('Longitud')
ax.set_ylabel('Latitud')
plt.show()
# Ploteo de la una reproyección del archivo "puntos_shapefile" (se verifica si existe o no una mala Proyección)
# WGS84 Proyección: 4326
# CRTM05 Proyección: 5367
regiones_proyectada = regiones.to_crs('EPSG:4326')
fig = plt.figure()
ax = fig.add_subplot(111)
regiones_proyectada.plot(ax=ax, fc='none',ec='black')
plt.title('Regiones de Costa Rica ' + str(regiones_proyectada.crs))
ax.set_xlabel('Coordenada Este (Y)')
ax.set_ylabel('Coordenada Norte (X)')
plt.show()
Al generar el paso anterior, seguidamente se procede a verificar la similitud de los plots gdf_puntos y regiones_proyectada¶
In [ ]:
gdf_puntos.plot()
regiones_proyectada.plot()
Opcion 2 : Se carga el shape PSA_2019_WGS84, se visualiza el contenido del shapefile de contratos PSA 2019 y se crea un GeoDataFrame.¶
Se accede a la información de la tabla de atributos del shapefile PSA 2019¶
In [ ]:
#Se accede al contenido del shapefile PSA_2019_WGS84, en sus primeras 5 lineas.
sf_path = r'/content/PSA_2019_WGS84.shp'
sf_df = gpd.read_file(sf_path)
sf_df.head()
Se verifica la geometría del GeoDataframe sf_df¶
- Elemento de lista
- Elemento de lista
In [ ]:
sf_df.geometry.type
Se adiciona una nueva columna "geometry_points" para obtener de cada multipoligono un centroide.¶
In [ ]:
sf_df["geometry_points"] = sf_df["geometry"].centroid
sf_df.head()
Se genera el plot de las ubicaciones de los contratos PSA 2019 mediante puntos¶
In [ ]:
import geopandas as gpd
import matplotlib.pyplot as plt
# Supongamos que tienes un DataFrame llamado "gdf" con una columna "geometry_points"
# que contiene los centroides de tus polígonos
# Crear una figura y un eje
fig, ax = plt.subplots(figsize=(5, 5))
# Trazar los centroides desde la columna "geometry_points"
sf_df["geometry_points"].plot(ax=ax, color='blue', markersize=5)
# Personalizar el gráfico (opcional)
ax.set_title("Centroides de los polígonos")
ax.set_xlabel("Longitud")
ax.set_ylabel("Latitud")
# Mostrar el gráfico
plt.show()
** *Tomamos la opcion 1 y ejecutamos lo siguiente:* **¶
Se carga el archivo de las Provincias de Costa Rica en formato Geojson y se crea un nuevo GEodataframe¶
In [ ]:
#Se Carga la capa de Provincias de Costa Rica
ruta_archivo = "/content/ProvinciasCR_WGS84.geojson"
gdf = gpd.read_file(ruta_archivo)
mapa_CR = gdf
mapa_CR.plot(figsize= (8,8),edgecolor = 'black')
Se adiciona al Geodataframe "mapa_CR" una nueva columna que corresponde a la delimitación de cada una de la provincias "boundary"¶
In [ ]:
mapa_CR['boundary'] = mapa_CR.boundary
mapa_CR
In [ ]:
#Vamos a graficar los proyectos PSA por cada una de las Provincias
Alajuela = mapa_CR[mapa_CR['PROVINCIA'] == 'ALAJUELA']
Alajuela.plot()
Guanacaste = mapa_CR[mapa_CR['PROVINCIA'] == 'GUANACASTE']
Guanacaste.plot()
Limon = mapa_CR[mapa_CR['PROVINCIA'] == 'LIMON']
Limon.plot()
Heredia = mapa_CR[mapa_CR['PROVINCIA'] == 'HEREDIA']
Heredia.plot()
SanJose = mapa_CR[mapa_CR['PROVINCIA'] == 'SAN JOSE']
SanJose.plot()
Cartago = mapa_CR[mapa_CR['PROVINCIA'] == 'CARTAGO']
Cartago.plot()
Puntarenas = mapa_CR[mapa_CR['PROVINCIA'] == 'PUNTARENAS']
Puntarenas.plot()
In [ ]:
# Ploteo sólo los registros de Alajuela en el DF de Alajuela
#provincia = "ALAJUELA"
provincia = "GUANACASTE"
#provincia = "LIMON"
filtered_obvs = gdf_puntos[gdf_puntos["PROVINCIA"] == provincia]
prov_map = mapa_CR[mapa_CR["PROVINCIA"] == provincia]
# Ploteo del mapa
lienzo = prov_map.plot(figsize = (7,7), color="lightgreen", edgecolor="black", linewidth = 0.6)
# Asignar título
title = f'Obvservaciones registradas en {provincia}'
# lienzo.set_title(title)
lienzo.axis("off")
# Labels
# lienzo.set_ylabel("Latitud")
# lienzo.set_xlabel("Longitud")
# Ploteo de los puntos
filtered_obvs.plot(ax=lienzo, color="k")
** *Se calcula la estadística para los valores numéricos* **¶
In [ ]:
df1_filled.describe()
Interpretación de las variables estadísticas¶
* Área(ha) contratadas: Aunque el promedio de área contratada para el PSA corresponde con 64.8 ha, se establece que los valores para las desviaciones oscilan entre ± 129.4 ha.¶
* Edad: Utilizando la mediana como medida de tendencia central, se determinó que 64 años es la edad más frecuente para los propietarios en el programa PSA con contratos vigentes.¶
In [ ]:
#Se categorizaron las edades usando un rango de 10 años
df2 = df1_filled.copy()
# Definir los límites de los rangos (intervalos)
rangos = [4.9, 29.9, 39.9, 49.9, 59.9, 69.9, 79.9, 89.9, 125]
# Etiquetas para los bins
labels = ['<29', '30-39.9', '40-49.9', '50-59.9', '60-69.9', '70-79.9', '80-89.9', '>90']
# Aplicar discretización
df2['rangoEdad'] = pd.cut(df2['edadSegunReporte'], bins=rangos, labels=labels, include_lowest=True)
display(df2[['rangoEdad', 'edadSegunReporte']])
In [ ]:
# Prueba de la clasificación de la edad segun la estimación anterior.
display(df2.loc[df2['rangoEdad'] == '50-59.9', ['rangoEdad', 'edadSegunReporte']])
In [ ]:
contValores= df2.groupby('rangoEdad')['valor'].sum()
contValores
conVal69 = df2['rangoEdad'] == '60-69.9'
conVal69_r = conVal69.sum()
conVal69_r
fig, ax = plt.subplots()
ax.plot(labels, contValores, label= 'Grupo etario', color = 'tab:blue')
# # Título del gráfico
ax.set_title('Frecuencia de las observaciones respecto al grupo etario')
# # Etiqueta del eje X
ax.set_xlabel('Grupo etario', fontdict = {'fontsize':14, 'fontweight':'bold', 'color':'tab:gray'})
# # Etiqueta del eje Y
ax.set_ylabel('Frecuencia')
# # Indicar que línea corresponde a qué columna (leyenda)
ax.legend(loc='upper right')
histograma= df2.hist(column='edadSegunReporte', bins=9)
display(histograma)
# # Mostrar cuadrícula en el gráfico
ax.grid(True)
ax.set_xticks(range(0, 9))
plt.setp(ax.get_xticklabels(), rotation=0)
plt.show()
Del análisis anterior, se estima que el rango de la edad que oscila entre los 60-69.9 años fueron los que mostraron la mayor frecuencia de contratos inscritos (1834 unidades), lo cual podría guardar relación con la edad en que muchos de los propietarios prefieren desarrollar actividades relacionadas con la protección del bosque y abandonas otras actividades productivas como la ganadería y la agricultura.¶
In [ ]:
#Distribucion de la frecuancia por tipo de cliente
dfgrupoEdad= df2.groupby('Tipo Cliente')['valor'].sum()
dfgrupoEdad
In [ ]:
#Grafico Apilado de Frecuencias
ct= pd.crosstab(df2['rangoEdad'], df2['Tipo Cliente'])
print(ct)
barplot = ct.plot.bar(stacked=True)
In [ ]:
df_MasFem= pd.DataFrame(
[
['<29', 20, 5],
['30-39.9', 124, 48],
['40-49.9', 210, 104],
['50-59.9', 446, 219],
['60-69.9', 600, 321],
['70-79-9', 423, 271],
['80,89.9', 174, 91],
['>90', 51, 31]
],
index= [1, 2, 3, 4, 5, 6, 7, 8],
columns= ['rangoEdad', 'Mujer', 'Hombre']
)
df_MasFem
In [ ]:
# Diagrama de estructura de la edad
import plotly.graph_objects as gp
y_edad = df_MasFem['rangoEdad']
x_Fem= df_MasFem['Mujer'] * -1
x_Masc= df_MasFem['Hombre']
fig = gp.Figure()
fig.add_trace(gp.Bar(y=y_edad, x= x_Fem, name= 'Mujer', orientation= 'h'))
fig.add_trace(gp.Bar(y=y_edad, x= x_Masc, name= 'Hombre', orientation= 'h'))
fig.update_layout(title= 'Distribución de la edad por género',
title_font_size= 22, barmode= 'relative',
bargap= 0.0, bargroupgap= 0,
xaxis= dict(tickvals= [-600, -300, 0, 300, 600],
ticktext=['600', '300',
'0', '300', '600'],
title= "Frecuencia para la edad de los propietarios",
title_font_size=14)
)
fig.show()