Изменение порядка записей для легенды геопанды на карте - PullRequest
0 голосов
/ 25 января 2019

Я наношу на карту определенную категориальную стоимость. Строка кода, которую я использую для построения графика, следующая:

fig = plt.figure(figsize=(12, 12))
ax = plt.gca()
urban_data.plot(column="category", cmap="viridis", ax=ax, categorical=True, /
                k=4, legend=True, linewidth=0.5, /
                legend_kwds={'fontsize':'19', 'loc':'lower left'}) 

где городские данные - это геопандас, и я использую matplotlib в качестве библиотеки черчения. Аргумент legend_kwds позволяет мне контролировать второстепенные вещи в легенде, такие как положение или размер шрифта, но я не могу решить основные вещи, такие как, например, порядок записей в поле легенды. На самом деле мои категории ранжируются, скажем, 1-2-3-4, но я всегда отображаю их в другом порядке.

Возможно ли иметь больше контроля над легендой? Например, вызывая его за пределами функции gdf.plot()? И, если да, как мне сопоставить цвета в легенде с цветами на карте, которые представляют собой дискретные значения (которые я точно не знаю) цветовой карты viridis?


РЕДАКТИРОВАТЬ: вот проверяемый пример. К сожалению, шейп-файлам нужны другие файлы для работы, и здесь необходим столбец geometry (область, а не точка), поэтому я должен попросить вас загрузить этот shpfile из США. Все, что вам нужно, находится в этой папке. Вот код, чтобы воспроизвести проблему. Сюжет на выходе плохой, потому что я не заботился о системе координат здесь, но важна легенда.

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

gdf=gpd.read_file('.../USA_adm1.shp')
clusters=np.random.randint(0,4, size=52)
gdf['cluster']=clusters
clusdict={1: 'lower-middle', 2: 'upper-middle', 3: 'upper', 0: 'lower'}
gdf['cluster']=gdf['cluster'].map(clusdict)

fig = plt.figure(figsize=(12, 12))
ax = plt.gca()
gdf.plot(column='cluster',cmap='viridis', categorical=True, legend=True, ax=ax)

Ответы [ 2 ]

0 голосов
/ 26 января 2019

Плохая новость заключается в том, что категории в легендах, создаваемых геопандами, сортируются, и это жестко закодировано ( см. Исходный код здесь ).

Следовательно, одно из решений состоит в том, чтобы иметь такой категориальный столбецчто если он отсортирован, он будет соответствовать желаемому порядку.Использование целых чисел, кажется, хорошо для этого.Затем можно заменить имена в легенде, если они произведены в правильном порядке.

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

gdf=gpd.read_file('data/USA_adm/USA_adm1.shp')
clusters=np.random.randint(0,4, size=52)
gdf['cluster']=clusters
clusdict={1: 'lower-middle', 2: 'upper-middle', 3: 'upper', 0: 'lower'}

fig = plt.figure(figsize=(12, 12))
ax = plt.gca()
gdf.plot(column='cluster',cmap='viridis', categorical=True, legend=True, ax=ax)

def replace_legend_items(legend, mapping):
    for txt in legend.texts:
        for k,v in mapping.items():
            if txt.get_text() == str(k):
                txt.set_text(v)

replace_legend_items(ax.get_legend(), clusdict)

plt.show()

enter image description here

0 голосов
/ 25 января 2019

Предполагая, что у вас есть 4 легенды, вы можете сделать следующее, чтобы установить их в любом порядке. Следующий код показывает, как разместить их в следующем порядке (с использованием индекса): 0, 2, 3, 1.

Здесь ax - объект оси, который вы определили с помощью ax = plt.gca()

handles,labels = ax.get_legend_handles_labels()
handles = [handles[0], handles[2], handles[3], handles[1]]
labels = [labels[0], labels[2], labels[3], labels[1]]
ax.legend(handles, labels)

Позвольте привести пример:

Порядок по умолчанию

fig, ax = plt.subplots()

x = np.arange(5)
plt.plot(x, x, label=r'$y=x$')
plt.plot(x, 2*x, label=r'$y=2x$')
plt.plot(x, 3*x, label=r'$y=3x$')
plt.plot(x, 4*x, label=r'$y=4x$')
plt.legend(fontsize=16)    

enter image description here

Вручную измененный заказ

fig, ax = plt.subplots()

x = np.arange(5)
plt.plot(x, x, label=r'$y=x$')
plt.plot(x, 2*x, label=r'$y=2x$')
plt.plot(x, 3*x, label=r'$y=3x$')
plt.plot(x, 4*x, label=r'$y=4x$')

handles,labels = ax.get_legend_handles_labels()
handles = [handles[0], handles[2],handles[3], handles[1]]
labels = [labels[0], labels[2], labels[3], labels[1]]
ax.legend(handles, labels, fontsize=16)

Можно также использовать понимание списка, используя заранее заданный список заказов как

order = [0, 2, 3, 1]
handles,labels = ax.get_legend_handles_labels()
handles = [handles[i] for i in order]
labels = [labels[i] for i in order]
ax.legend(handles, labels, fontsize=16)

enter image description here

...