Элегантный способ импорта данных в geo pandas GeoDataFrame - PullRequest
0 голосов
/ 18 июня 2020

У меня есть источник данных, основанный на кодах стран ISO3, и я использую sh, чтобы визуализировать его с помощью geo pandas. Источник, который я использую, основан на данных мирового банка и содержит больше стран, чем целевое значение в GeoDataFrame.

Я использовал приведенный ниже код для достижения визуализации, которую искал. Некоторые строки кода исправляют отсутствующие сокращения в слое world (см. https://github.com/geopandas/geopandas/issues/1041 для получения дополнительной информации).

Теперь у меня две проблемы.

  1. (major) Код не очень изящный. Кто-нибудь знает, что более элегантно было импортировать данные в world GeoDataFrame?
  2. (второстепенный) Я получаю предупреждение matplotlib, которого я не понимаю:

RuntimeWarning: invalid value encountered in less xa[xa < 0] = -1

Basi c код для воспроизведения проблемы приведен ниже. Извините за длинные массивы, но данные необходимы для воспроизведения проблемы.

import numpy as np
import matplotlib.pyplot as plt
import geopandas as gpd 

# resulting data after a lot of operations
c = np.array([1, 6, 6, 1, 6, 6, 6, 5, 5, 5, 7, 5, 5, 7, 5, 6, 5, 6, 7, 5, 7, 7,
       6, 7, 6, 4, 6, 1, 1, 7, 7, 5, 1, 1, 5, 6, 6, 6, 7, 1, 7, 6, 1, 5,
       6, 5, 5, 5, 7, 6, 6, 6, 7, 6, 2, 7, 5, 1, 6, 5, 5, 5, 7, 1, 6, 5,
       7, 5, 5, 6, 5, 7, 1, 1, 7, 7, 6, 5, 5, 5, 7, 7, 6, 7, 5, 5, 5, 6,
       5, 6, 6, 7, 7, 5, 5, 7, 7, 6, 6, 7, 1, 6, 5, 6, 5, 5, 6, 7, 1, 6,
       7, 1, 5, 6, 7, 6, 6, 7, 6, 7, 6, 7, 1, 7, 7, 7, 5, 5, 5, 6, 1, 1,
       5, 5, 3, 6, 6, 7, 6, 6, 6, 5, 5, 5, 5, 6, 6, 1, 6, 5, 7, 5, 7, 6,
       8, 1, 5, 5, 5, 7, 1, 6, 5, 6, 6, 6, 6, 7, 6, 7, 5, 5, 6, 7, 1, 6,
       1, 7, 6, 5, 6, 7, 7, 7, 1, 6, 4, 5, 5, 6, 7, 6, 6, 6, 5, 7, 7, 1,
       7], dtype=int)
iso3c = np.array(['AFG', 'ALB', 'DZA', 'AGO', 'ATG', 'ARG', 'ARM', 'ABW', 'AUS',
       'AUT', 'AZE', 'BHS', 'BHR', 'BGD', 'BRB', 'BLR', 'BEL', 'BLZ',
       'BEN', 'BMU', 'BTN', 'BOL', 'BIH', 'BWA', 'BRA', 'BRN', 'BGR',
       'BFA', 'BDI', 'KHM', 'CMR', 'CAN', 'CAF', 'TCD', 'CHI', 'CHL',
       'CHN', 'COL', 'COM', 'COD', 'COG', 'CRI', 'CIV', 'HRV', 'CUB',
       'CYP', 'CZE', 'DNK', 'DJI', 'DMA', 'DOM', 'ECU', 'EGY', 'SLV',
       'GNQ', 'ERI', 'EST', 'ETH', 'FJI', 'FIN', 'FRA', 'PYF', 'GAB',
       'GMB', 'GEO', 'DEU', 'GHA', 'GRC', 'GRL', 'GRD', 'GUM', 'GTM',
       'GIN', 'GNB', 'GUY', 'HTI', 'HND', 'HKG', 'HUN', 'ISL', 'IND',
       'IDN', 'IRN', 'IRQ', 'IRL', 'ISR', 'ITA', 'JAM', 'JPN', 'JOR',
       'KAZ', 'KEN', 'KIR', 'KOR', 'KWT', 'KGZ', 'LAO', 'LVA', 'LBN',
       'LSO', 'LBR', 'LBY', 'LIE', 'LTU', 'LUX', 'MAC', 'MKD', 'MDG',
       'MWI', 'MYS', 'MDV', 'MLI', 'MLT', 'MHL', 'MRT', 'MUS', 'MEX',
       'FSM', 'MDA', 'MNG', 'MNE', 'MAR', 'MOZ', 'MMR', 'NAM', 'NPL',
       'NLD', 'NCL', 'NZL', 'NIC', 'NER', 'NGA', 'NOR', 'OMN', 'PAK',
       'PLW', 'PAN', 'PNG', 'PRY', 'PER', 'PHL', 'POL', 'PRT', 'PRI',
       'QAT', 'ROU', 'RUS', 'RWA', 'WSM', 'SMR', 'STP', 'SAU', 'SEN',
       'SRB', 'SYC', 'SLE', 'SGP', 'SVK', 'SVN', 'SLB', 'SOM', 'ZAF',
       'ESP', 'LKA', 'KNA', 'LCA', 'VCT', 'SDN', 'SUR', 'SWZ', 'SWE',
       'CHE', 'SYR', 'TJK', 'TZA', 'THA', 'TLS', 'TGO', 'TON', 'TTO',
       'TUN', 'TUR', 'TKM', 'TUV', 'UGA', 'UKR', 'ARE', 'GBR', 'USA',
       'URY', 'UZB', 'VUT', 'VEN', 'VNM', 'VIR', 'PSE', 'YEM', 'ZMB',
       'ZWE'], dtype=object)

world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
# just done because of an existing bug 
world.loc[world['name'] == 'France', 'iso_a3'] = 'FRA'
world.loc[world['name'] == 'Norway', 'iso_a3'] = 'NOR'
world.loc[world['name'] == 'Somaliland', 'iso_a3'] = 'SOM'
world.loc[world['name'] == 'Kosovo', 'iso_a3'] = 'RKS'

world = world[(world.pop_est>0) & (world.name!="Antarctica")]

plotData = np.nan * np.ones(world.iso_a3.shape[0])
for i, country in enumerate(iso3c) :
    for j, wcountry in enumerate(world.iso_a3) :
        if country == wcountry:
            plotData[j] = float(c[i])
world.plot(plotData, cmap='Paired')    

1 Ответ

2 голосов
/ 18 июня 2020

Я думаю, вам было бы полезно поместить ваши массивы в фрейм данных, а затем объединить его с вашим world фреймом геоданных. Итак, что бы вы получили:

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import geopandas as gpd 

def fix_missing_codes(world):
    # just done because of an existing bug 
    world2 = world.copy()

    world2.loc[world['name'] == 'France', 'iso_a3'] = 'FRA'
    world2.loc[world['name'] == 'Norway', 'iso_a3'] = 'NOR'
    world2.loc[world['name'] == 'Somaliland', 'iso_a3'] = 'SOM'
    world2.loc[world['name'] == 'Kosovo', 'iso_a3'] = 'RKS'
    return world2

c = np.array([...])
iso3c = np.array([...])

colors = pd.DataFrame({
    'color': c,
    'iso_a3': iso3c
})

ax = (
    gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
        .loc[lambda df: (df['pop_est'] > 0) & (df['name'] != 'Antarctica')]
        .pipe(fix_missing_codes)
        .merge(colors, on='iso_a3')
        .plot(column='color', cmap='Paired')
)

Это также избавит вас от вашего предупреждения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...