为 geopandas.explore 图创建自定义颜色图
Creating custom colourmap for geopandas.explore plot
所有代码:
def rgb2hex(r,g,b):
return '#{:02x}{:02x}{:02x}'.format(r,g,b)
def rg(num):
num = int(np.round((num / 100) * 124))
r = (124 - num)
g = (124 + num)
b = (0)
x = rgb2hex(r,g,b)
return x
def colourmap(value):
if math.isnan(value) == False:
y = rg(value)
else:
y = '#808080'
return y
m = homes.explore(
column="Percentage",
cmap=lambda value: colourmap(value),#map to custom colour scheme
marker_kwds=dict(radius=15, fill=True), # make marker radius 15px with fill
tooltip=labels, # show labels in the tooltip
legend=False,
name="Homes" # name of the layer in the map
)
m #plot
您好,我对 Whosebug 和使用 geopandas 比较陌生,因此欢迎任何意见。
我正在尝试创建处理 NaN 值的自定义配色方案。
绿色表示百分比高,黄色表示百分比低但灰色表示 NaN。
但是我得到这个错误:
ValueError Traceback (most recent call last)
_______________________________________.ipynb Cell 33' in <module>
3 labels = ["Worker Type","Postcode","Name","Percentage"]
---> 16 m = homes.explore(
17 column="Percentage",
18 cmap=lambda value: colourmap(value)
19 marker_kwds=dict(radius=15, fill=True)
20 tooltip=labels
22 legend=False, # do not show column label in the tooltip
23 name="Homes" # name of the layer in the map
File ____________________\ref_env\lib\site-packages\geopandas\geodataframe.py:1858, in GeoDataFrame.explore(self, *args, **kwargs)
1855 @doc(_explore)
1856 def explore(self, *args, **kwargs):
1857 """Interactive map based on folium/leaflet.js"""
-> 1858 return _explore(self, *args, **kwargs)
File ________________\ref_env\lib\site-packages\geopandas\explore.py:457, in _explore(df, column, cmap, color, m, tiles, attr, tooltip, popup, highlight, categorical, legend, scheme, k, vmin, vmax, width, height, categories, classification_kwds, control_scale, marker_type, marker_kwds, style_kwds, highlight_kwds, missing_kwds, tooltip_kwds, popup_kwds, legend_kwds, **kwargs)
454 nan_color = missing_kwds.pop("color", None)
456 gdf["__folium_color"] = nan_color
--> 457 gdf.loc[~nan_idx, "__folium_color"] = color
458 else:
459 gdf["__folium_color"] = color
File _______________\ref_env\lib\site-packages\pandas\core\indexing.py:723, in _LocationIndexer.__setitem__(self, key, value)
720 self._has_valid_setitem_indexer(key)
722 iloc = self if self.name == "iloc" else self.obj.iloc
--> 723 iloc._setitem_with_indexer(indexer, value, self.name)
File _________________\ref_env\lib\site-packages\pandas\core\indexing.py:1730, in _iLocIndexer._setitem_with_indexer(self, indexer, value, name)
1727 # align and set the values
1728 if take_split_path:
1729 # We have to operate column-wise
-> 1730 self._setitem_with_indexer_split_path(indexer, value, name)
1731 else:
1732 self._setitem_single_block(indexer, value, name)
File ______________\ref_env\lib\site-packages\pandas\core\indexing.py:1785, in _iLocIndexer._setitem_with_indexer_split_path(self, indexer, value, name)
1780 if len(value) == 1 and not is_integer(info_axis):
1781 # This is a case like df.iloc[:3, [1]] = [0]
1782 # where we treat as df.iloc[:3, 1] = 0
1783 return self._setitem_with_indexer((pi, info_axis[0]), value[0])
-> 1785 raise ValueError(
1786 "Must have equal len keys and value "
1787 "when setting with an iterable"
1788 )
1790 elif lplane_indexer == 0 and len(value) == len(self.obj.index):
1791 # We get here in one case via .loc with a all-False mask
1792 pass
ValueError: Must have equal len keys and value when setting with an iterable
有人可以向我描述这个错误并指导我下一步看哪里吗?
编辑:我应该包括我正在使用点几何
- 已使用标准几何模拟此问题的数据
- 当 cmap 是可调用的并且它们是 中的 NaN 值时,我发现的似乎是一个错误列
- 已经解决了
fillna(-99)
- 调整你的
colormap()
函数来处理 -99 与 NaN
- 根据围绕 JSON 序列化的评论扩展了答案。创建了一个功能列。测试列是 JSON 可序列化的,然后排除不可序列化的列
我在 geopandas 中对
explore()
做出了改进。我正在研究导致此问题/错误的参数排列。将针对 Geopandas 提出问题并可能提交 PR。与此同时,我建议使用上述解决方法。
更新 产生了一个问题 https://github.com/geopandas/geopandas/issues/2408
import geopandas as gpd
import numpy as np
import math
import json
def rgb2hex(r, g, b):
return "#{:02x}{:02x}{:02x}".format(r, g, b)
def rg(num):
num = int(np.round((num / 100) * 124))
r = 124 - num
g = 124 + num
b = 0
x = rgb2hex(r, g, b)
return x
def colourmap(value):
if value != -99 and math.isnan(value) == False: # changed to treat -99 as NaN :-(
y = rg(value)
else:
y = "#808080"
return y
# some geometry to demonstrate
def foo():
return True
homes = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
homes["Percentage"] = np.random.randint(1, 100, len(homes))
homes["func_col"] = foo
homes.loc[homes.sample(20).index, "Percentage"] = np.nan
# miss this line and error is generated...
homes["Percentage"] = homes["Percentage"].fillna(-99)
excl = {}
for c in homes.columns:
try:
json.dumps(homes[c].to_dict())
except TypeError as e:
if c != "geometry":
excl[c] = str(e)
m = homes.loc[:, [c for c in homes.columns if c not in excl.keys()]].explore(
column="Percentage",
cmap=lambda value: colourmap(value), # map to custom colour scheme
marker_kwds=dict(radius=15, fill=True), # make marker radius 15px with fill
# tooltip=labels, # show labels in the tooltip
legend=False,
name="Homes", # name of the layer in the map
)
m # plot
结合 Rob 的回答和评论中的讨论,这是我最终使用的最终解决方案:
import geopandas as gpd
import numpy as np
import math
import json
import random
import pandas as pd
import random
def rgb2hex(r, g, b):
return "#{:02x}{:02x}{:02x}".format(r, g, b)
def rg(p):
d = [255,0,0]
d[1] = int((510*p)/100)
if d[1]>255:
d[0] -= d[1]-255
d[1] = 255
x = rgb2hex(d[0],d[1],d[2])
return x
def colourmap(value):
if value != -99 and math.isnan(value) == False: # changed to treat -99 as NaN :-(
y = rg(value)
else:
y = "#808080"
return y
def foo(df):
x = np.random.randint(-180, 180, len(df))
y = np.random.randint(-90, 90, len(df))
s = gpd.GeoSeries.from_xy(x, y, crs="EPSG:4326")
return s
homes = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
homes["Percentage"] = np.random.randint(1, 100, len(homes))
homes["func_col"] = foo(homes)
homes.loc[homes.sample(20).index, "Percentage"] = np.nan
# miss this line and error is generated...
homes["Percentage"] = homes["Percentage"].fillna(-99)
homes = homes.set_geometry('func_col')
excl = {}
for c in homes.columns:
try:
json.dumps(homes[c].to_dict())
except TypeError as e:
if c != "geometry":
excl[c] = str(e)
m = homes.explore(
column="Percentage",
cmap=lambda value: colourmap(value),
marker_kwds=dict(radius=15, fill=True), # make marker radius 15px with fill
tooltip=["name"], # show "name" column in the tooltip
legend_kwds=dict(caption="Percentage",colorbar=True), # do not use colorbar
legend=False, # do not show column label in the tooltip
name="homes" # name of the layer in the map
)
m
所有代码:
def rgb2hex(r,g,b):
return '#{:02x}{:02x}{:02x}'.format(r,g,b)
def rg(num):
num = int(np.round((num / 100) * 124))
r = (124 - num)
g = (124 + num)
b = (0)
x = rgb2hex(r,g,b)
return x
def colourmap(value):
if math.isnan(value) == False:
y = rg(value)
else:
y = '#808080'
return y
m = homes.explore(
column="Percentage",
cmap=lambda value: colourmap(value),#map to custom colour scheme
marker_kwds=dict(radius=15, fill=True), # make marker radius 15px with fill
tooltip=labels, # show labels in the tooltip
legend=False,
name="Homes" # name of the layer in the map
)
m #plot
您好,我对 Whosebug 和使用 geopandas 比较陌生,因此欢迎任何意见。
我正在尝试创建处理 NaN 值的自定义配色方案。
绿色表示百分比高,黄色表示百分比低但灰色表示 NaN。
但是我得到这个错误:
ValueError Traceback (most recent call last)
_______________________________________.ipynb Cell 33' in <module>
3 labels = ["Worker Type","Postcode","Name","Percentage"]
---> 16 m = homes.explore(
17 column="Percentage",
18 cmap=lambda value: colourmap(value)
19 marker_kwds=dict(radius=15, fill=True)
20 tooltip=labels
22 legend=False, # do not show column label in the tooltip
23 name="Homes" # name of the layer in the map
File ____________________\ref_env\lib\site-packages\geopandas\geodataframe.py:1858, in GeoDataFrame.explore(self, *args, **kwargs)
1855 @doc(_explore)
1856 def explore(self, *args, **kwargs):
1857 """Interactive map based on folium/leaflet.js"""
-> 1858 return _explore(self, *args, **kwargs)
File ________________\ref_env\lib\site-packages\geopandas\explore.py:457, in _explore(df, column, cmap, color, m, tiles, attr, tooltip, popup, highlight, categorical, legend, scheme, k, vmin, vmax, width, height, categories, classification_kwds, control_scale, marker_type, marker_kwds, style_kwds, highlight_kwds, missing_kwds, tooltip_kwds, popup_kwds, legend_kwds, **kwargs)
454 nan_color = missing_kwds.pop("color", None)
456 gdf["__folium_color"] = nan_color
--> 457 gdf.loc[~nan_idx, "__folium_color"] = color
458 else:
459 gdf["__folium_color"] = color
File _______________\ref_env\lib\site-packages\pandas\core\indexing.py:723, in _LocationIndexer.__setitem__(self, key, value)
720 self._has_valid_setitem_indexer(key)
722 iloc = self if self.name == "iloc" else self.obj.iloc
--> 723 iloc._setitem_with_indexer(indexer, value, self.name)
File _________________\ref_env\lib\site-packages\pandas\core\indexing.py:1730, in _iLocIndexer._setitem_with_indexer(self, indexer, value, name)
1727 # align and set the values
1728 if take_split_path:
1729 # We have to operate column-wise
-> 1730 self._setitem_with_indexer_split_path(indexer, value, name)
1731 else:
1732 self._setitem_single_block(indexer, value, name)
File ______________\ref_env\lib\site-packages\pandas\core\indexing.py:1785, in _iLocIndexer._setitem_with_indexer_split_path(self, indexer, value, name)
1780 if len(value) == 1 and not is_integer(info_axis):
1781 # This is a case like df.iloc[:3, [1]] = [0]
1782 # where we treat as df.iloc[:3, 1] = 0
1783 return self._setitem_with_indexer((pi, info_axis[0]), value[0])
-> 1785 raise ValueError(
1786 "Must have equal len keys and value "
1787 "when setting with an iterable"
1788 )
1790 elif lplane_indexer == 0 and len(value) == len(self.obj.index):
1791 # We get here in one case via .loc with a all-False mask
1792 pass
ValueError: Must have equal len keys and value when setting with an iterable
有人可以向我描述这个错误并指导我下一步看哪里吗?
编辑:我应该包括我正在使用点几何
- 已使用标准几何模拟此问题的数据
- 当 cmap 是可调用的并且它们是 中的 NaN 值时,我发现的似乎是一个错误列
- 已经解决了
fillna(-99)
- 调整你的
colormap()
函数来处理 -99 与 NaN
- 根据围绕 JSON 序列化的评论扩展了答案。创建了一个功能列。测试列是 JSON 可序列化的,然后排除不可序列化的列
我在 geopandas 中对
explore()
做出了改进。我正在研究导致此问题/错误的参数排列。将针对 Geopandas 提出问题并可能提交 PR。与此同时,我建议使用上述解决方法。
更新 产生了一个问题 https://github.com/geopandas/geopandas/issues/2408
import geopandas as gpd
import numpy as np
import math
import json
def rgb2hex(r, g, b):
return "#{:02x}{:02x}{:02x}".format(r, g, b)
def rg(num):
num = int(np.round((num / 100) * 124))
r = 124 - num
g = 124 + num
b = 0
x = rgb2hex(r, g, b)
return x
def colourmap(value):
if value != -99 and math.isnan(value) == False: # changed to treat -99 as NaN :-(
y = rg(value)
else:
y = "#808080"
return y
# some geometry to demonstrate
def foo():
return True
homes = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
homes["Percentage"] = np.random.randint(1, 100, len(homes))
homes["func_col"] = foo
homes.loc[homes.sample(20).index, "Percentage"] = np.nan
# miss this line and error is generated...
homes["Percentage"] = homes["Percentage"].fillna(-99)
excl = {}
for c in homes.columns:
try:
json.dumps(homes[c].to_dict())
except TypeError as e:
if c != "geometry":
excl[c] = str(e)
m = homes.loc[:, [c for c in homes.columns if c not in excl.keys()]].explore(
column="Percentage",
cmap=lambda value: colourmap(value), # map to custom colour scheme
marker_kwds=dict(radius=15, fill=True), # make marker radius 15px with fill
# tooltip=labels, # show labels in the tooltip
legend=False,
name="Homes", # name of the layer in the map
)
m # plot
结合 Rob 的回答和评论中的讨论,这是我最终使用的最终解决方案:
import geopandas as gpd
import numpy as np
import math
import json
import random
import pandas as pd
import random
def rgb2hex(r, g, b):
return "#{:02x}{:02x}{:02x}".format(r, g, b)
def rg(p):
d = [255,0,0]
d[1] = int((510*p)/100)
if d[1]>255:
d[0] -= d[1]-255
d[1] = 255
x = rgb2hex(d[0],d[1],d[2])
return x
def colourmap(value):
if value != -99 and math.isnan(value) == False: # changed to treat -99 as NaN :-(
y = rg(value)
else:
y = "#808080"
return y
def foo(df):
x = np.random.randint(-180, 180, len(df))
y = np.random.randint(-90, 90, len(df))
s = gpd.GeoSeries.from_xy(x, y, crs="EPSG:4326")
return s
homes = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
homes["Percentage"] = np.random.randint(1, 100, len(homes))
homes["func_col"] = foo(homes)
homes.loc[homes.sample(20).index, "Percentage"] = np.nan
# miss this line and error is generated...
homes["Percentage"] = homes["Percentage"].fillna(-99)
homes = homes.set_geometry('func_col')
excl = {}
for c in homes.columns:
try:
json.dumps(homes[c].to_dict())
except TypeError as e:
if c != "geometry":
excl[c] = str(e)
m = homes.explore(
column="Percentage",
cmap=lambda value: colourmap(value),
marker_kwds=dict(radius=15, fill=True), # make marker radius 15px with fill
tooltip=["name"], # show "name" column in the tooltip
legend_kwds=dict(caption="Percentage",colorbar=True), # do not use colorbar
legend=False, # do not show column label in the tooltip
name="homes" # name of the layer in the map
)
m