BUG: fix incorrect colors with mixed geometry types and list of colors (#2420)

This commit is contained in:
rraymondgh
2022-06-07 14:33:50 +02:00
committed by GitHub
parent 793900d4be
commit aa7e9c97d8
2 changed files with 60 additions and 6 deletions
+18 -6
View File
@@ -325,7 +325,7 @@ def plot_series(
----------
s : Series
The GeoSeries to be plotted. Currently Polygon,
MultiPolygon, LineString, MultiLineString and Point
MultiPolygon, LineString, MultiLineString, Point and MultiPoint
geometries can be plotted.
cmap : str (default None)
The name of a colormap recognized by matplotlib. Any
@@ -335,7 +335,7 @@ def plot_series(
tab10, tab20, Accent, Dark2, Paired, Pastel1, Set1, Set2
color : str (default None)
color : str, np.array, pd.Series, List (default None)
If specified, all objects will be colored uniformly.
ax : matplotlib.pyplot.Artist (default None)
axes on which to draw the plot
@@ -414,6 +414,9 @@ def plot_series(
)
return ax
# have colors been given for all geometries?
color_given = pd.api.types.is_list_like(color) and len(color) == len(s)
# if cmap is specified, create range of colors based on cmap
values = None
if cmap is not None:
@@ -426,6 +429,10 @@ def plot_series(
# decompose GeometryCollections
geoms, multiindex = _flatten_multi_geoms(s.geometry, prefix="Geom")
values = np.take(values, multiindex, axis=0) if cmap else None
# ensure indexes are consistent
if color_given and isinstance(color, pd.Series):
color = color.reindex(s.index)
expl_color = np.take(color, multiindex, axis=0) if color_given else color
expl_series = geopandas.GeoSeries(geoms)
geom_types = expl_series.type
@@ -443,8 +450,9 @@ def plot_series(
# color overrides both face and edgecolor. As we want people to be
# able to use edgecolor as well, pass color to facecolor
facecolor = style_kwds.pop("facecolor", None)
color_ = expl_color[poly_idx] if color_given else color
if color is not None:
facecolor = color
facecolor = color_
values_ = values[poly_idx] if cmap else None
_plot_polygon_collection(
@@ -455,16 +463,20 @@ def plot_series(
lines = expl_series[line_idx]
if not lines.empty:
values_ = values[line_idx] if cmap else None
color_ = expl_color[line_idx] if color_given else color
_plot_linestring_collection(
ax, lines, values_, color=color, cmap=cmap, **style_kwds
ax, lines, values_, color=color_, cmap=cmap, **style_kwds
)
# plot all Points in the same collection
points = expl_series[point_idx]
if not points.empty:
values_ = values[point_idx] if cmap else None
color_ = expl_color[point_idx] if color_given else color
_plot_point_collection(
ax, points, values_, color=color, cmap=cmap, **style_kwds
ax, points, values_, color=color_, cmap=cmap, **style_kwds
)
plt.draw()
@@ -524,7 +536,7 @@ def plot_dataframe(
- 'hexbin' : hexbin plot.
cmap : str (default None)
The name of a colormap recognized by matplotlib.
color : str (default None)
color : str, np.array, pd.Series (default None)
If specified, all objects will be colored uniformly.
ax : matplotlib.pyplot.Artist (default None)
axes on which to draw the plot
+42
View File
@@ -16,6 +16,7 @@ from shapely.geometry import (
MultiPoint,
MultiLineString,
GeometryCollection,
box,
)
@@ -871,6 +872,47 @@ class TestPolygonZPlotting:
self.df.plot()
class TestColorParamArray:
def setup_method(self):
geom = []
color = []
for a, b in [(0, 2), (4, 6)]:
b = box(a, a, b, b)
geom += [b, b.buffer(0.8).exterior, b.centroid]
color += ["red", "green", "blue"]
self.gdf = GeoDataFrame({"geometry": geom, "color_rgba": color})
self.mgdf = self.gdf.dissolve(self.gdf.type)
def test_color_single(self):
ax = self.gdf.plot(color=self.gdf["color_rgba"])
_check_colors(
4,
np.concatenate([c.get_edgecolor() for c in ax.collections]),
["green"] * 2 + ["blue"] * 2,
)
_check_colors(
4,
np.concatenate([c.get_facecolor() for c in ax.collections]),
["red"] * 2 + ["blue"] * 2,
)
def test_color_multi(self):
ax = self.mgdf.plot(color=self.mgdf["color_rgba"])
_check_colors(
4,
np.concatenate([c.get_edgecolor() for c in ax.collections]),
["green"] * 2 + ["blue"] * 2,
)
_check_colors(
4,
np.concatenate([c.get_facecolor() for c in ax.collections]),
["red"] * 2 + ["blue"] * 2,
)
class TestGeometryCollectionPlotting:
def setup_method(self):
coll1 = GeometryCollection(