Repository: geopandas/geopandas

Issue:
BUG: path_effects not working in geopandas.plot with multiple entities
- [X] I have checked that this issue has not already been reported.

- [X] I have confirmed this bug exists on the latest version of geopandas.

- [ ] (optional) I have confirmed this bug exists on the master branch of geopandas.

---

#### Code Sample, a copy-pastable example

```python
import geopandas as gpd
import matplotlib.pyplot as plt

from shapely.geometry import LineString
from matplotlib.collections import LineCollection

import matplotlib.patheffects as PathEffects

# Create lines
lines = [LineString([[0, 0], [1, 1]]),
         LineString([[0, 1], [1, 2]]),
         LineString([[0, 2], [1, 3]])]
names = ['A', 'B', 'B']
d = dict(name=names, geometry=lines)
gdf = gpd.GeoDataFrame(d, crs="EPSG:4326")

fig, axes = plt.subplots(1, 2, sharex=True, sharey=True)
effects=[PathEffects.withStroke(linewidth=8,
                                foreground='b')]

# Path effects in line collection works fine
axes[0].set_title('LineCollection plot')
col1 = LineCollection((lines[0].coords,),
                      color='orange', linewidth=3,
                      path_effects=effects)
axes[0].add_collection(col1)
col2 = LineCollection((lines[1].coords, lines[2].coords),
                      color='green', linewidth=3,
                      path_effects=effects)
axes[0].add_collection(col2)


# Plot with geopandas with path_effects

axes[1].set_title('geopandas plot')

# Works fine when there is only one geometry
gdf[gdf['name']=='A'].plot(ax=axes[1], color='orange',  linewidth=3,
                           path_effects=effects)
# Not working with multiple geometries
gdf[gdf['name']=='B'].plot(ax=axes[1], color='green',  linewidth=3,
                           path_effects=effects)
```

#### Problem description

when .plot() is used on a geodataframe with multiple geometries (at least LineStrings), specifying a path_effects raises an error. This is because path_effects must be given as a list, and _expand_kwargs in plotting.py assumes it has the same number of elements as the number of geometries. Hoewever, using a list of lists (in the above example, that would be path_effects = [effects, effects]) does not work either, because _expand_kwargs returns an array. Then, the drawer of the LineCollection (in collections.py) checks if it has path_effects with the test 
```
if self.get_path_effects()
```
It raises an error, because get_path_effects yields an array, and the truth value of an array with more than one element is ambiguous.

#### Expected Output

I would expect geopandas.plot() to work as the LineCollection constructor that is used for plotting lines. That is, we should be able to specify one path_effects that is applied to all geometries (it does not seem possible to apply one path_effect per Line in LineCollection, at least directly in the constructor). 

A workaround is to construct a LineCollection from the geopandasdataframe, but that is not very handy...

#### Output of ``geopandas.show_versions()``

Geopandas was installed through the conda-forge channel of anaconda. 

<details>

SYSTEM INFO
-----------
python     : 3.9.6 | packaged by conda-forge | (default, Jul  6 2021, 08:46:02) [MSC v.1916 64 bit (AMD64)]
executable : C:\Users\peruzzetto\Anaconda3\envs\maps\python.exe
machine    : Windows-10-10.0.19042-SP0

GEOS, GDAL, PROJ INFO
---------------------
GEOS       : None
GEOS lib   : None
GDAL       : 3.2.1
GDAL data dir: None
PROJ       : 7.2.0
PROJ data dir: C:\Users\peruzzetto\Anaconda3\envs\maps\Library\share\proj

PYTHON DEPENDENCIES
-------------------
geopandas  : 0.9.0
pandas     : 1.3.0
fiona      : 1.8.18
numpy      : 1.21.0
shapely    : 1.7.1
rtree      : 0.9.7
pyproj     : 3.1.0
matplotlib : 3.4.2
mapclassify: 2.4.3
geopy      : None
psycopg2   : None
geoalchemy2: None
pyarrow    : None
pygeos     : None

</details>



Discussion:

Resolving patch:
diff --git a/geopandas/plotting.py b/geopandas/plotting.py
--- a/geopandas/plotting.py
+++ b/geopandas/plotting.py
@@ -73,9 +73,9 @@ def _expand_kwargs(kwargs, multiindex):
     mpl = matplotlib.__version__
     if mpl >= LooseVersion("3.4") or (mpl > LooseVersion("3.3.2") and "+" in mpl):
         # alpha is supported as array argument with matplotlib 3.4+
-        scalar_kwargs = ["marker"]
+        scalar_kwargs = ["marker", "path_effects"]
     else:
-        scalar_kwargs = ["marker", "alpha"]
+        scalar_kwargs = ["marker", "alpha", "path_effects"]
 
     for att, value in kwargs.items():
         if "color" in att:  # color(s), edgecolor(s), facecolor(s)


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
@@ -550,6 +550,16 @@ def test_style_kwargs_alpha(self):
                 np.linspace(0, 0.0, 1.0, self.N), ax.collections[0].get_alpha()
             )
 
+    def test_style_kwargs_path_effects(self):
+        from matplotlib.patheffects import withStroke
+
+        effects = [withStroke(linewidth=8, foreground="b")]
+        ax = self.df.plot(color="orange", path_effects=effects)
+        assert ax.collections[0].get_path_effects()[0].__dict__["_gc"] == {
+            "linewidth": 8,
+            "foreground": "b",
+        }
+
     def test_subplots_norm(self):
         # colors of subplots are the same as for plot (norm is applied)
         cmap = matplotlib.cm.viridis_r
@@ -1660,7 +1670,7 @@ def _style_to_linestring_onoffseq(linestyle, linewidth):
 
 
 def _style_to_vertices(markerstyle):
-    """ Converts a markerstyle string to a path. """
+    """Converts a markerstyle string to a path."""
     # TODO: Vertices values are twice the actual path; unclear, why.
     path = matplotlib.markers.MarkerStyle(markerstyle).get_path()
     return path.vertices / 2