Repository: geopandas/geopandas

Issue:
Pass keywords to colorbar construction
Hey all,
Amazing tool – thank you so much for putting it together and managing it so well.

I'm sure there is an easy fix to this, but I'm having trouble accessing the legend object from a chloropleth plot. I'd imagine ax.get_legend() should return it, but that doesn't seem to be the case.

My endgoal is simply to put the colormap horizontally beneath my figure – so if there's a very easy way to do that let me know. Thank you so much!



Discussion:
Hi @b-tierney ,

your question looks more related to colorbars/legends in matplotlib.
If you're handling continuous values, you can try the snippet below to orient the colorbar.

```python
from matplotlib.colors import Normalize
from matplotlib import cm

import geopandas as gpd
gdf = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres')) 

ax = gdf.plot(column='gdp_md_est', legend=False)
mn = gdf.gdp_md_est.min()
mx = gdf.gdp_md_est.max()
norm = Normalize(vmin=mn, vmax=mx)
n_cmap = cm.ScalarMappable(norm=norm, cmap="viridis")
n_cmap.set_array([])
ax.get_figure().colorbar(n_cmap, ax=ax, orientation='horizontal')
```
HTH
BTW, I'm wondering whether adding `colorbar_kwds` in `plot_dataframe` would be useful ?
Or, we could pass the `legend_kwds` to the colorbar? (since it's either a legend or either a colorbar depnding on the data, and `legend=True` targets both)
I'm so sorry about the slow response – that snippet did the trick, of course, I was just being dumb.

In any case, colorbar_kwds would certainly be useful and intuitive for an already spectacular tool.

Thanks again, really appreciate the assist.

Let's leave it open for implementing the ability to pass keywords to the colorbar construction (by either passing the existing `legend_kwds` or by adding a `colorbar_kwds`)
I think there should also be a `colorbar=Ture` instead of `legend=True` since the color doesn't really believe like a legend.
I encounter this quite often that folks seek a way to set the midpoint of a colorbar to `0`. Please consider adding an arg in the `colorbar_kwds` like `dict(center=0)` or something to support this:

```python
import geopandas as gpd
import matplotlib.pyplot as plt
import matplotlib.colors as colors

# generate data
gdf = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
gdf['random'] = np.random.gamma(2, 2, len(gdf)) - 2

# normalize color
vmin, vmax, vcenter = gdf.random.min(), gdf.random.max(), 0
divnorm = colors.DivergingNorm(vmin=vmin, vcenter=vcenter, vmax=vmax)
# create a normalized colorbar
cbar = plt.cm.ScalarMappable(norm=divnorm, cmap='RdBu')

# plot
fig, ax = plt.subplots(figsize=(15, 7))
gdf.plot(column='random', cmap='RdBu', legend=False, norm=divnorm, ax=ax)
# add colorbar
fig.colorbar(cbar, ax=ax)
```
![download](https://user-images.githubusercontent.com/33796896/61963146-0299c600-af99-11e9-9ec0-15ff4dac7168.png)

I wonder if this should be added to the [doc](http://geopandas.org/mapping.html) here. 
We can think about adding keywords for controlling this behaviour, feel free to draft a PR. 

Regarding your example, personally I would not add it to docs, but we can make an example out of it. However, not in a way you showed as color scheme is not the same in blues and reds (dark blue is much more extreme value than dark red), so the map is slightly misleading in this case.
@martinfleis Could you label this issue as PR wanted or something? 

> dark blue is much more extreme value than dark red

I think this is intended since the data distribution is skewed.

Resolving patch:
diff --git a/geopandas/plotting.py b/geopandas/plotting.py
--- a/geopandas/plotting.py
+++ b/geopandas/plotting.py
@@ -590,7 +590,9 @@ def plot_dataframe(
         from matplotlib.colors import Normalize
         from matplotlib import cm
 
-        norm = Normalize(vmin=mn, vmax=mx)
+        norm = style_kwds.get("norm", None)
+        if not norm:
+            norm = Normalize(vmin=mn, vmax=mx)
         n_cmap = cm.ScalarMappable(norm=norm, cmap=cmap)
         if categorical:
             patches = []


Test patch:
diff --git a/geopandas/tests/test_plotting.py b/geopandas/tests/test_plotting.py
--- a/geopandas/tests/test_plotting.py
+++ b/geopandas/tests/test_plotting.py
@@ -45,7 +45,9 @@ def setup_method(self):
         self.points = GeoSeries(Point(i, i) for i in range(self.N))
 
         values = np.arange(self.N)
+
         self.df = GeoDataFrame({"geometry": self.points, "values": values})
+        self.df["exp"] = (values * 10) ** 3
 
         multipoint1 = MultiPoint(self.points)
         multipoint2 = rotate(multipoint1, 90)
@@ -176,6 +178,21 @@ def test_legend(self):
         # last point == top of colorbar
         np.testing.assert_array_equal(point_colors[-1], cbar_colors[-1])
 
+        # # Normalized legend
+        # the colorbar matches the Point colors
+        norm = matplotlib.colors.LogNorm(
+            vmin=self.df[1:].exp.min(), vmax=self.df[1:].exp.max()
+        )
+        ax = self.df[1:].plot(column="exp", cmap="RdYlGn", legend=True, norm=norm)
+        point_colors = ax.collections[0].get_facecolors()
+        cbar_colors = ax.get_figure().axes[1].collections[0].get_facecolors()
+        # first point == bottom of colorbar
+        np.testing.assert_array_equal(point_colors[0], cbar_colors[0])
+        # last point == top of colorbar
+        np.testing.assert_array_equal(point_colors[-1], cbar_colors[-1])
+        # colorbar generated proper long transition
+        assert cbar_colors.shape == (256, 4)
+
     def test_subplots_norm(self):
         # colors of subplots are the same as for plot (norm is applied)
         cmap = matplotlib.cm.viridis_r