Создать плотно ScatterMapbox из панд данных - PullRequest
0 голосов
/ 19 июня 2019

Я хотел бы создать диаграмму рассеяния для Индонезии для различных статистических данных (население, ВВП и т. Д.) На региональной основе.Я работаю с файлом геопанды из github .

Пример на веб-сайте plotly создает несколько файлов для каждого слоя, а затем использует ссылку github в качестве источника.

#republican counties
source = 'https://raw.githubusercontent.com/plotly/datasets/master/florida-red-data.json'  
#democrat counties
source = 'https://raw.githubusercontent.com/plotly/datasets/master/florida-blue-data.json'

Поэтому мой вопрос состоит в том, как я могу использовать фрейм данных pandas для создания наслоения слоя для каждого региона и использовать его в качестве источника (а также раскрашивать каждый регион конкретными значениями в других фреймах данных).Если это вообще невозможно, и необходимо создать отдельный файл для каждого региона, как бы я это сделал?Моя попытка (строки 16-20) не сработала

import pandas as pd
import json
import string
import plotly
from plotly.graph_objs import Scattermapbox, Layout
ID_regions = pd.read_json('https://raw.githubusercontent.com/N1x0/indonesia-geojson/master/indonesia-edit.geojson')

region_names = []

for region in ID_regions['features']:
    region_names.append(state['properties']['name'])

print(region_names)

#This shit creates json and doesn't work
def create_region_files():
    for i in range(len(ID_regions)):
        region_data = ID_regions.iloc[i,:]
        region_data.to_json(f'C:\\Users\\nicho\\Desktop\\Waste Management\\Map_Maker\\ID_regions\\{region_names[i]}.json')
        i += 1


def create_Chloropleth():
    mapbox_access_token = 'My Access Key'

    data = [
        Scattermapbox(
            lat=['45.5017'],
            lon=['-73.5673'],
            mode='markers',
        )
    ]
    layout = Layout(
        height=900,
        autosize=True,
        showlegend=False,
        hovermode='closest',
        mapbox=dict(
            layers=[
                dict(
                    sourcetype = 'geojson',
                    source = 'https://raw.githubusercontent.com/N1x0/indonesia-geojson/master/indonesia-edit.geojson',
                    type = 'fill',
                    color = 'green'
                ),
                dict(
                    sourcetype = 'geojson',
                    source = 'https://raw.githubusercontent.com/N1x0/indonesia-geojson/master/west-sulawesi.json',
                    type = ' fill',
                    color = 'red',
                )
            ],
            accesstoken=mapbox_access_token,
            bearing=0,
            center=dict(
                lat=0.7893,
                lon=113.9213
            ),
            pitch=0,
            zoom=4.5,
            style='light'
        ),
    )

    fig = dict(data=data, layout=layout)
    plotly.offline.plot(fig, filename='Chloropleth_Province_Population.html')

create_Chloropleth()

Спасибо за помощь!

1 Ответ

0 голосов
/ 22 июня 2019

Хорошо, у меня ушло немного времени, но я все понял. Большое спасибо Эмме Гримальди за Medium и Винсу Поте . Их посты были тем, что помогло мне в большинстве случаев. Так что вот ответы на мой вопрос по порядку:

  1. Нет необходимости создавать отдельный файл для каждого региона. То есть Вы можете использовать pandas dataframe для сопоставления названий регионов в json, и это будет прекрасно работать.

with open('indonesia-en.geojson') as f: geojson = json.load(f)

def make_sources(downsample = 0):
    sources = []
    geojson_copy = copy.deepcopy(geojson['features']) # do not overwrite the original file
    for feature in geojson_copy:

        if downsample > 0:
            coords = np.array(feature['geometry']['coordinates'][0][0])
            coords = coords[::downsample]
            feature['geometry']['coordinates'] = [[coords]]

        sources.append(dict(type = 'FeatureCollection',
                            features = [feature])
                      )
    return sources

То есть вы просто извлекаете координаты из геойсона и добавляете их в список диктов [{}].

  1. Как использовать этот список для динамического создания слоев:
    MAPBOX_APIKEY = "Your API Key"
    data = dict(type='scattermapbox',
                lat=lats,
                lon=lons,
                mode='markers',
                text=hover_text,
                marker=dict(size=1,
                            color=scatter_colors,
                            showscale = True,
                            cmin = minpop/1000000,
                            cmax = maxpop/1000000,
                            colorscale = colorscale,
                            colorbar = dict(
                            title='Population in Millions'
                            )
                           ),
                showlegend=False,
                hoverinfo='text'
                 )

    layers=([dict(sourcetype = 'geojson',
                  source =sources[k],
                  below="water",
                  type = 'line',    # the borders
                  line = dict(width = 1),
                  color = 'black',
                  ) for k in range(n_provinces) # where n_provinces = len(geojson['features'])
              ] +

            [dict(sourcetype = 'geojson',
                  source =sources[k],
                  type = 'fill',   # the area inside the borders
                  color = scatter_colors[k],
                  opacity=0.8
                 ) for k in range(n_provinces)  # where n_provinces = len(geojson['features'])
             ]
            )

Таким образом, решение здесь слишком установлено sources = sources[k] Т.е. список с указанием значений широты и долготы, созданный в make_sources()

  1. Как соответствующим образом раскрасить слои color=scatter_colors[k]

Используя связанный пример, я использовал 3 функции

3,1 scalarmappable

#sets colors based on min and max values
def scalarmappable(cmap, cmin, cmax):
        colormap = cm.get_cmap(cmap)
        norm = Normalize(vmin=cmin, vmax=cmax+(cmax*0.10)) #vmax get's increased 10 percent because otherwise the most populous region doesnt get colored
        return cm.ScalarMappable(norm=norm, cmap=colormap)

3,2 scatter_colors

#uses matplotlib to create colors based on values and sets grey for isnan value
def get_scatter_colors(sm, df):
grey = 'rgba(128,128,128,1)'
return ['rgba' + str(sm.to_rgba(m, bytes = True, alpha = 1)) if not np.isnan(m) else grey for m in df]  

3,3 colorscale

#defines horizontal range and corresponding values for colorscale
def get_colorscale(sm, df, cmin, cmax):
    xrange = np.linspace(0, 1, len(df))
    values = np.linspace(cmin, cmax, len(df))

    return [[i, 'rgba' + str(sm.to_rgba(v, bytes = True))] for i,v in zip(xrange, values) ]

Затем устанавливаются переменные с использованием функций

#assigning values
colormap = 'nipy_spectral'
minpop = stats['population'].min()
maxpop = stats['population'].max()
sources = make_sources(downsample=0)
lons, lats = get_centers()

sm = scalarmappable(colormap, minpop, maxpop)
scatter_colors = get_scatter_colors(sm, stats['population'])
colorscale = get_colorscale(sm, stats, minpop, maxpop)
hover_text = get_hover_text(stats['population'])

Так что, если у кого-то возникли проблемы с этим ответом, он может помочь вам прогрессировать:)

...