Saltar al contenido

Geopandas: ¿cómo trazar países/ciudades?

Esta cuestión se puede resolver de diversas maneras, pero en este caso te dejamos la solución más completa en nuestra opinión.

Solución:

Según el código que ha publicado, no puedo ver nada malo en el trazado, por lo que supongo que el problema podría estar en algún lugar de su agregación o fusión de datos.

Aquí hay una solución que comienza generando datos que deberían ser similares a los suyos, luego cuenta la cantidad de veces que aparece un país en los datos como una proporción del tamaño del conjunto de datos, ya que esta es la métrica requerida. Nos centraremos en usar solo algunos países como ejemplo:

from random import choices
import pandas as pd
import numpy as np

def generate_data():
    
    k = 100
    
    countries_of_interest = ['USA','ARG','BRA','GBR','ESP','RUS']
    countries = choices(countries_of_interest, k=k)
    
    start_yr = 2010
    end_yr = 2021
    
    return pd.DataFrame('Country':countries, 
                         'Year':np.random.randint(start_yr, end_yr, k),
                        index=range(len(countries)))


def aggregate_data(df):
    data = df.groupby('Country').agg('count')*100.0/len(df)
    data = data.reset_index().rename(columns='Year':'proportion_of_dataset')
    return data

df = generate_data()

#    Country  Year
# 0      USA  2017
# 1      GBR  2014
# 2      USA  2013
# 3      BRA  2016
# 4      BRA  2018
# ..     ...   ...
# 95     ESP  2014
# 96     USA  2015
# 97     RUS  2019
# 98     RUS  2012
# 99     RUS  2011
# 
# [100 rows x 2 columns]

data = aggregate_data(df)

#   Country  proportion_of_dataset
# 0     ARG                   20.0
# 1     BRA                   17.0
# 2     ESP                   14.0
# 3     GBR                   14.0
# 4     RUS                   19.0
# 5     USA                   16.0

Ahora cargue el archivo de forma de la frontera del país usando geopandas y cambie el nombre de las columnas:

import geopandas as gpd

shapefile = 'path_to_shapfile_folder/ne_110m_admin_0_countries/ne_110m_admin_0_countries.shp'
gdf = gpd.read_file(shapefile)[['ADMIN', 'ADM0_A3', 'geometry']]
gdf.columns = ['country', 'country_code', 'geometry']

gdf.head()

#                        country country_code  
# 0                         Fiji          FJI   
# 1  United Republic of Tanzania          TZA   
# 2               Western Sahara          SAH   
# 3                       Canada          CAN   
# 4     United States of America          USA   
# 
#                                             geometry  
# 0  MULTIPOLYGON (((180.00000 -16.06713, 180.00000...  
# 1  POLYGON ((33.90371 -0.95000, 34.07262 -1.05982...  
# 2  POLYGON ((-8.66559 27.65643, -8.66512 27.58948...  
# 3  MULTIPOLYGON (((-122.84000 49.00000, -122.9742...  
# 4  MULTIPOLYGON (((-122.84000 49.00000, -120.0000...

Ahora queremos fusionar el marco de datos del polígono del país con nuestros datos agregados. Nota: queremos hacer una combinación izquierda (en el marco de datos del polígono de país completo) para incluir todos los países, incluso aquellos para los que no tenemos datos. También tenga en cuenta que estamos agregando valores faltantes para estos países llenando NaN con ceros:

merged = gdf.merge(data, left_on = 'country_code', right_on = 'Country', how='left')
merged['proportion_of_dataset'] = merged['proportion_of_dataset'].fillna(0)

Usando su código para crear el geojson:

import json

merged_json = json.loads(merged.to_json())
json_data = json.dumps(merged_json)

Finalmente, colocaremos su código de trazado en una función y pasaremos como argumentos el geojson, la columna para trazar y el título de la trama:

from bokeh.io import output_notebook, show, output_file
from bokeh.plotting import figure
from bokeh.models import GeoJSONDataSource, LinearColorMapper, ColorBar
from bokeh.palettes import brewer

def plot_map(json_data,plot_col,title):

    geosource = GeoJSONDataSource(geojson = json_data)

    #Define a sequential multi-hue color palette.
    palette = brewer['YlGnBu'][8]
    palette = palette[::-1]
    color_mapper = LinearColorMapper(palette = palette, low = 0, high = 40)

    tick_labels = '0': '0%', '5': '5%', '10':'10%', '15':'15%', '20':'20%', '25':'25%', '30':'30%','35':'35%', '40': '>40%'

    color_bar = ColorBar(color_mapper=color_mapper, label_standoff=8,width = 500, height = 20,
    border_line_color=None,location = (0,0), orientation = 'horizontal', major_label_overrides = tick_labels)

    p = figure(title = title, plot_height = 600 , plot_width = 950, toolbar_location = None)
    p.xgrid.grid_line_color = None
    p.ygrid.grid_line_color = None

    p.patches('xs','ys', source = geosource,fill_color = 'field' :plot_col, 'transform' : color_mapper,
              line_color = 'black', line_width = 0.25, fill_alpha = 1)

    p.add_layout(color_bar, 'below')

    output_notebook()

    #Display figure.
    show(p)

Ahora todo lo que tenemos que hacer es llamar a la función de trazado, pasando los parámetros requeridos:

plot_map(json_data,'proportion_of_dataset','Dataset countries of origin')

gráfico

Valoraciones y comentarios

Recuerda dar recomendación a esta noticia si lograste el éxito.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *