Copilot commented on code in PR #2193:
URL: https://github.com/apache/sedona/pull/2193#discussion_r2241215056


##########
python/sedona/geopandas/io.py:
##########
@@ -236,3 +236,50 @@ def read_file(filename: str, format: Union[str, None] = 
None, **kwargs):
 
     internal = InternalFrame(spark_frame=sdf, 
index_spark_columns=index_spark_columns)
     return GeoDataFrame(ps.DataFrame(internal))
+
+
+def read_parquet(
+    path,
+    columns=None,
+    storage_options=None,
+    bbox=None,
+    to_pandas_kwargs=None,
+    **kwargs,
+):
+    """
+    Load a Parquet object from the file path, returning a GeoDataFrame.
+
+    * if no geometry columns are read, this will raise a ``ValueError`` - you
+      should use the pandas `read_parquet` method instead.
+
+    If 'crs' key is not present in the GeoParquet metadata associated with the
+    Parquet object, it will default to "OGC:CRS84" according to the 
specification.
+
+    Parameters
+    ----------
+    path : str, path object
+    columns : list-like of strings, default=None
+        Not currently supported in Sedona
+    storage_options : dict, optional
+        Not currently supported in Sedona
+    bbox : tuple, optional
+        Not currently supported in Sedona
+    to_pandas_kwargs : dict, optional
+        Not currently supported in Sedona
+
+    Returns
+    -------
+    GeoDataFrame
+
+    Examples
+    --------
+    from sedona.geopandas import read_parquet
+    >>> df = read_parquet("data.parquet")  # doctest: +SKIP
+
+    Specifying columns to read:
+
+    >>> df = read_parquet(
+    ...     "data.parquet",
+    ... )  # doctest: +SKIP
+    """

Review Comment:
   The `read_parquet` function's docstring parameters section mentions several 
unsupported parameters (columns, storage_options, bbox, to_pandas_kwargs) but 
doesn't clearly indicate what happens when these are used. Consider adding a 
note about what occurs if unsupported parameters are passed.
   ```suggestion
       """
       unsupported_params = ['columns', 'storage_options', 'bbox', 
'to_pandas_kwargs']
       for param in unsupported_params:
           if param in kwargs:
               warnings.warn(
                   f"The parameter '{param}' is not supported and will be 
ignored.",
                   UserWarning,
               )
   ```



##########
python/tests/geopandas/test_plotting.py:
##########
@@ -0,0 +1,2086 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# This file is copied from geopandas/tests/test_plotting.py
+# and was modified to skip the tests that require data files.
+
+import itertools
+import warnings
+
+import numpy as np
+import pandas as pd
+
+import pytest
+import shapely
+import geopandas as gpd
+from packaging.version import parse as parse_version
+
+if parse_version(shapely.__version__) < parse_version("2.0.0"):
+    pytest.skip(f"Tests require shapely>=2.0.0", allow_module_level=True)
+
+if parse_version(gpd.__version__) < parse_version("1.0.0"):
+    pytest.skip(f"Tests require geopandas>=1.0.0", allow_module_level=True)
+
+from shapely.affinity import rotate
+from shapely.geometry import (
+    GeometryCollection,
+    LinearRing,
+    LineString,
+    MultiLineString,
+    MultiPoint,
+    MultiPolygon,
+    Point,
+    Polygon,
+    box,
+)
+
+GEOS_GE_390 = True
+HAS_PYPROJ = True
+
+from geopandas import GeoDataFrame, GeoSeries, read_file
+from geopandas.plotting import GeoplotAccessor
+
+matplotlib = pytest.importorskip("matplotlib")
+matplotlib.use("Agg")
+import matplotlib.pyplot as plt
+
+try:  # skipif and importorskip do not work for decorators
+    # Skip these tests in Sedona repo since data is not included in this repo
+    raise ImportError
+    # Original code
+    # from matplotlib.testing.decorators import check_figures_equal, 
image_comparison
+
+    # MPL_DECORATORS = True
+except ImportError:
+    MPL_DECORATORS = False
+
+
[email protected](autouse=True)
+def close_figures(request):
+    yield
+    plt.close("all")
+
+
+try:
+    cycle = matplotlib.rcParams["axes.prop_cycle"].by_key()
+    MPL_DFT_COLOR = cycle["color"][0]
+except KeyError:
+    MPL_DFT_COLOR = matplotlib.rcParams["axes.color_cycle"][0]
+
+plt.rcParams.update({"figure.max_open_warning": 0})
+
+
+class TestPointPlotting:
+    def setup_method(self):
+        self.N = 10
+        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)
+        self.df2 = GeoDataFrame(
+            {"geometry": [multipoint1, multipoint2], "values": [0, 1]}
+        )
+
+    def test_figsize(self):
+        ax = self.points.plot(figsize=(1, 1))
+        np.testing.assert_array_equal(ax.figure.get_size_inches(), (1, 1))
+
+        ax = self.df.plot(figsize=(1, 1))
+        np.testing.assert_array_equal(ax.figure.get_size_inches(), (1, 1))
+
+    def test_default_colors(self):
+        # # without specifying values -> uniform color
+
+        # GeoSeries
+        ax = self.points.plot()
+        _check_colors(
+            self.N, ax.collections[0].get_facecolors(), [MPL_DFT_COLOR] * 
self.N
+        )
+
+        # GeoDataFrame
+        ax = self.df.plot()
+        _check_colors(
+            self.N, ax.collections[0].get_facecolors(), [MPL_DFT_COLOR] * 
self.N
+        )
+
+        # # with specifying values -> different colors for all 10 values
+        ax = self.df.plot(column="values")
+        cmap = plt.get_cmap()
+        expected_colors = cmap(np.arange(self.N) / (self.N - 1))
+        _check_colors(self.N, ax.collections[0].get_facecolors(), 
expected_colors)
+
+    def test_series_color_no_index(self):
+        # Color order with ordered index
+        colors_ord = pd.Series(["a", "b", "c", "a", "b", "c", "a", "b", "c", 
"a"])
+
+        # Plot using Series as color
+        ax1 = self.df.plot(colors_ord)
+
+        # Correct answer: Add as column to df and plot
+        self.df["colors_ord"] = colors_ord
+        ax2 = self.df.plot("colors_ord")
+
+        # Confirm out-of-order index re-sorted
+        point_colors1 = ax1.collections[0].get_facecolors()
+        point_colors2 = ax2.collections[0].get_facecolors()
+        np.testing.assert_array_equal(point_colors1[1], point_colors2[1])
+
+    def test_series_color_index(self):
+        # Color order with out-of-order index
+        colors_ord = pd.Series(
+            ["a", "a", "a", "a", "b", "b", "b", "c", "c", "c"],
+            index=[0, 3, 6, 9, 1, 4, 7, 2, 5, 8],
+        )
+
+        # Plot using Series as color
+        ax1 = self.df.plot(colors_ord)
+
+        # Correct answer: Add as column to df and plot
+        self.df["colors_ord"] = colors_ord
+        ax2 = self.df.plot("colors_ord")
+
+        # Confirm out-of-order index re-sorted
+        point_colors1 = ax1.collections[0].get_facecolors()
+        point_colors2 = ax2.collections[0].get_facecolors()
+        np.testing.assert_array_equal(point_colors1[1], point_colors2[1])
+
+    def test_colormap(self):
+        # without specifying values but cmap specified -> no uniform color
+        # but different colors for all points
+
+        # GeoSeries
+        ax = self.points.plot(cmap="RdYlGn")
+        cmap = plt.get_cmap("RdYlGn")
+        exp_colors = cmap(np.arange(self.N) / (self.N - 1))
+        _check_colors(self.N, ax.collections[0].get_facecolors(), exp_colors)
+
+        ax = self.df.plot(cmap="RdYlGn")
+        _check_colors(self.N, ax.collections[0].get_facecolors(), exp_colors)
+
+        # # with specifying values -> different colors for all 10 values
+        ax = self.df.plot(column="values", cmap="RdYlGn")
+        cmap = plt.get_cmap("RdYlGn")
+        _check_colors(self.N, ax.collections[0].get_facecolors(), exp_colors)
+
+        # when using a cmap with specified lut -> limited number of different
+        # colors
+        ax = self.points.plot(cmap=plt.get_cmap("Set1", lut=5))
+        cmap = plt.get_cmap("Set1", lut=5)
+        exp_colors = cmap(list(range(5)) * 2)
+        _check_colors(self.N, ax.collections[0].get_facecolors(), exp_colors)
+
+    def test_single_color(self):
+        ax = self.points.plot(color="green")
+        _check_colors(self.N, ax.collections[0].get_facecolors(), ["green"] * 
self.N)
+
+        ax = self.df.plot(color="green")
+        _check_colors(self.N, ax.collections[0].get_facecolors(), ["green"] * 
self.N)
+
+        # check rgba tuple GH1178
+        ax = self.df.plot(color=(0.5, 0.5, 0.5))
+        _check_colors(
+            self.N, ax.collections[0].get_facecolors(), [(0.5, 0.5, 0.5)] * 
self.N
+        )
+        ax = self.df.plot(color=(0.5, 0.5, 0.5, 0.5))
+        _check_colors(
+            self.N, ax.collections[0].get_facecolors(), [(0.5, 0.5, 0.5, 0.5)] 
* self.N
+        )
+        with pytest.raises((ValueError, TypeError)):
+            self.df.plot(color="not color")
+
+        with warnings.catch_warnings(record=True) as _:  # don't print warning
+            # 'color' overrides 'column'
+            ax = self.df.plot(column="values", color="green")
+            _check_colors(
+                self.N, ax.collections[0].get_facecolors(), ["green"] * self.N
+            )
+
+    def test_markersize(self):
+        ax = self.points.plot(markersize=10)
+        assert ax.collections[0].get_sizes() == [10]
+
+        ax = self.df.plot(markersize=10)
+        assert ax.collections[0].get_sizes() == [10]
+
+        ax = self.df.plot(column="values", markersize=10)
+        assert ax.collections[0].get_sizes() == [10]
+
+        ax = self.df.plot(markersize="values")
+        assert (ax.collections[0].get_sizes() == self.df["values"]).all()
+
+        ax = self.df.plot(column="values", markersize="values")
+        assert (ax.collections[0].get_sizes() == self.df["values"]).all()
+
+    def test_markerstyle(self):
+        ax = self.df2.plot(marker="+")
+        expected = _style_to_vertices("+")
+        np.testing.assert_array_equal(
+            expected, ax.collections[0].get_paths()[0].vertices
+        )
+
+    def test_style_kwargs(self):
+        ax = self.points.plot(edgecolors="k")
+        assert (ax.collections[0].get_edgecolor() == [0, 0, 0, 1]).all()
+
+    def test_style_kwargs_alpha(self):
+        ax = self.df.plot(alpha=0.7)
+        np.testing.assert_array_equal([0.7], ax.collections[0].get_alpha())
+        try:
+            ax = self.df.plot(alpha=np.linspace(0, 0.0, 1.0, self.N))
+        except TypeError:
+            # no list allowed for alpha up to matplotlib 3.3
+            pass
+        else:
+            np.testing.assert_array_equal(
+                np.linspace(0, 0.0, 1.0, self.N), ax.collections[0].get_alpha()
+            )
+
+    def test_legend(self):
+        with warnings.catch_warnings(record=True) as _:  # don't print warning
+            # legend ignored if color is given.
+            ax = self.df.plot(column="values", color="green", legend=True)
+            assert len(ax.get_figure().axes) == 1  # no separate legend axis
+
+        # legend ignored if no column is given.
+        ax = self.df.plot(legend=True)
+        assert len(ax.get_figure().axes) == 1  # no separate legend axis
+
+        # # Continuous legend
+        # the colorbar matches the Point colors
+        ax = self.df.plot(column="values", cmap="RdYlGn", legend=True)
+        point_colors = ax.collections[0].get_facecolors()
+        cbar_colors = 
_get_colorbar_ax(ax.get_figure()).collections[-1].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])
+
+        # # Categorical legend
+        # the colorbar matches the Point colors
+        ax = self.df.plot(column="values", categorical=True, legend=True)
+        point_colors = ax.collections[0].get_facecolors()
+        cbar_colors = ax.get_legend().axes.collections[-1].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])
+
+        # # 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 = 
_get_colorbar_ax(ax.get_figure()).collections[-1].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
+        norm = matplotlib.colors.Normalize(vmin=0, vmax=20)
+        ax = self.df.plot(column="values", cmap=cmap, norm=norm)
+        actual_colors_orig = ax.collections[0].get_facecolors()
+        exp_colors = cmap(np.arange(10) / (20))
+        np.testing.assert_array_equal(exp_colors, actual_colors_orig)
+        fig, ax = plt.subplots()
+        self.df[1:].plot(column="values", ax=ax, norm=norm, cmap=cmap)
+        actual_colors_sub = ax.collections[0].get_facecolors()
+        np.testing.assert_array_equal(actual_colors_orig[1], 
actual_colors_sub[0])
+
+    def test_empty_plot(self):
+        s = GeoSeries([Polygon()])
+        with pytest.warns(UserWarning):
+            ax = s.plot()
+        assert len(ax.collections) == 0
+        s = GeoSeries([])
+        with pytest.warns(UserWarning):
+            ax = s.plot()
+        assert len(ax.collections) == 0
+        df = GeoDataFrame([], columns=["geometry"])
+        with pytest.warns(UserWarning):
+            ax = df.plot()
+        assert len(ax.collections) == 0
+
+    def test_empty_geometry(self):
+        s = GeoSeries([Polygon([(0, 0), (1, 0), (1, 1)]), Polygon()])
+        ax = s.plot()
+        assert len(ax.collections) == 1
+
+        # more complex case with GEOMETRYCOLLECTION EMPTY, POINT EMPTY and NONE
+        poly = Polygon([(-1, -1), (-1, 2), (2, 2), (2, -1), (-1, -1)])
+        point = Point(0, 1)
+        point_ = Point(10, 10)
+        empty_point = Point()
+
+        gdf = GeoDataFrame(geometry=[point, empty_point, point_])
+        gdf["geometry"] = gdf.intersection(poly)
+        with warnings.catch_warnings():
+            # loc to add row calls concat internally, warning for pandas >=2.1
+            warnings.filterwarnings(
+                "ignore",
+                "The behavior of DataFrame concatenation with empty",
+                FutureWarning,
+            )
+            gdf.loc[3] = [None]
+        ax = gdf.plot()
+        assert len(ax.collections) == 1
+
+    @pytest.mark.parametrize(
+        "geoms",
+        [
+            [
+                box(0, 0, 1, 1),
+                box(7, 7, 8, 8),
+            ],
+            [
+                LineString([(1, 1), (1, 2)]),
+                LineString([(7, 1), (7, 2)]),
+            ],
+            [
+                Point(1, 1),
+                Point(7, 7),
+            ],
+        ],
+    )
+    def test_empty_geometry_colors(self, geoms):
+        s = GeoSeries(
+            geoms,
+            index=["r", "b"],
+        )
+        s2 = s.intersection(box(5, 0, 10, 10))
+        ax = s2.plot(color=["red", "blue"])
+        blue = np.array([0.0, 0.0, 1.0, 1.0])
+        if s.geom_type["r"] == "LineString":
+            
np.testing.assert_array_equal(ax.get_children()[0].get_edgecolor()[0], blue)
+        else:
+            
np.testing.assert_array_equal(ax.get_children()[0].get_facecolor()[0], blue)
+
+    def test_multipoints(self):
+        # MultiPoints
+        ax = self.df2.plot()
+        _check_colors(4, ax.collections[0].get_facecolors(), [MPL_DFT_COLOR] * 
4)
+
+        ax = self.df2.plot(column="values")
+        cmap = plt.get_cmap(lut=2)
+        expected_colors = [cmap(0)] * self.N + [cmap(1)] * self.N
+        _check_colors(20, ax.collections[0].get_facecolors(), expected_colors)
+
+        ax = self.df2.plot(color=["r", "b"])
+        # colors are repeated for all components within a MultiPolygon
+        _check_colors(20, ax.collections[0].get_facecolors(), ["r"] * 10 + 
["b"] * 10)
+
+    def test_multipoints_alpha(self):
+        ax = self.df2.plot(alpha=0.7)
+        np.testing.assert_array_equal([0.7], ax.collections[0].get_alpha())
+        try:
+            ax = self.df2.plot(alpha=[0.7, 0.2])
+        except TypeError:
+            # no list allowed for alpha up to matplotlib 3.3
+            pass
+        else:
+            np.testing.assert_array_equal(
+                [0.7] * 10 + [0.2] * 10, ax.collections[0].get_alpha()
+            )
+
+    def test_categories(self):
+        self.df["cats_object"] = ["cat1", "cat2"] * 5
+        self.df["nums"] = [1, 2] * 5
+        self.df["singlecat_object"] = ["cat2"] * 10
+        self.df["cats"] = pd.Categorical(["cat1", "cat2"] * 5)
+        self.df["singlecat"] = pd.Categorical(
+            ["cat2"] * 10, categories=["cat1", "cat2"]
+        )
+        self.df["cats_ordered"] = pd.Categorical(
+            ["cat2", "cat1"] * 5, categories=["cat2", "cat1"]
+        )
+        self.df["bool"] = [False, True] * 5
+        self.df["bool_extension"] = pd.array([False, True] * 5)
+        self.df["cats_string"] = pd.array(["cat1", "cat2"] * 5, dtype="string")
+
+        ax1 = self.df.plot("cats_object", legend=True)
+        ax2 = self.df.plot("cats", legend=True)
+        ax3 = self.df.plot("singlecat_object", categories=["cat1", "cat2"], 
legend=True)
+        ax4 = self.df.plot("singlecat", legend=True)
+        ax5 = self.df.plot("cats_ordered", legend=True)
+        ax6 = self.df.plot("nums", categories=[1, 2], legend=True)
+        ax7 = self.df.plot("bool", legend=True)
+        ax8 = self.df.plot("bool_extension", legend=True)
+        ax9 = self.df.plot("cats_string", legend=True)
+
+        point_colors1 = ax1.collections[0].get_facecolors()
+        for ax in [ax2, ax3, ax4, ax5, ax6, ax7, ax8, ax9]:
+            point_colors2 = ax.collections[0].get_facecolors()
+            np.testing.assert_array_equal(point_colors1[1], point_colors2[1])
+
+        legend1 = [x.get_markerfacecolor() for x in 
ax1.get_legend().get_lines()]
+        for ax in [ax2, ax3, ax4, ax5, ax6, ax7, ax8, ax9]:
+            legend2 = [x.get_markerfacecolor() for x in 
ax.get_legend().get_lines()]
+            np.testing.assert_array_equal(legend1, legend2)
+
+        with pytest.raises(TypeError):
+            self.df.plot(column="cats_object", categories="non_list")
+
+        with pytest.raises(
+            ValueError, match="Column contains values not listed in 
categories."
+        ):
+            self.df.plot(column="cats_object", categories=["cat1"])
+
+        with pytest.raises(
+            ValueError, match="Cannot specify 'categories' when column has"
+        ):
+            self.df.plot(column="cats", categories=["cat1"])
+
+    def test_missing(self):
+        self.df.loc[0, "values"] = np.nan
+        ax = self.df.plot("values")
+        cmap = plt.get_cmap()
+        expected_colors = cmap(np.arange(self.N - 1) / (self.N - 2))
+        _check_colors(self.N - 1, ax.collections[0].get_facecolors(), 
expected_colors)
+
+        ax = self.df.plot("values", missing_kwds={"color": "r"})
+        cmap = plt.get_cmap()
+        expected_colors = cmap(np.arange(self.N - 1) / (self.N - 2))
+        _check_colors(1, ax.collections[1].get_facecolors(), ["r"])
+        _check_colors(self.N - 1, ax.collections[0].get_facecolors(), 
expected_colors)
+
+        ax = self.df.plot(
+            "values", missing_kwds={"color": "r"}, categorical=True, 
legend=True
+        )
+        _check_colors(1, ax.collections[1].get_facecolors(), ["r"])
+        point_colors = ax.collections[0].get_facecolors()
+        nan_color = ax.collections[1].get_facecolors()
+        leg_colors = ax.get_legend().axes.collections[0].get_facecolors()
+        leg_colors1 = ax.get_legend().axes.collections[1].get_facecolors()
+        np.testing.assert_array_equal(point_colors[0], leg_colors[0])
+        np.testing.assert_array_equal(nan_color[0], leg_colors1[0])
+
+    def test_no_missing_and_missing_kwds(self):
+        # GH2210
+        df = self.df.copy()
+        df["category"] = df["values"].astype("str")
+        df.plot("category", missing_kwds={"facecolor": "none"}, legend=True)
+
+    @pytest.mark.skip(reason="failing on older versions for uninvestigated 
reasons")
+    def test_missing_aspect(self):
+        self.df.loc[0, "values"] = np.nan
+        ax = self.df.plot(
+            "values",
+            missing_kwds={"color": "r"},
+            categorical=True,
+            legend=True,
+            aspect=2,
+        )
+        assert ax.get_aspect() == 2
+
+
+class TestPointZPlotting:
+    def setup_method(self):
+        self.N = 10
+        self.points = GeoSeries(Point(i, i, i) for i in range(self.N))
+        values = np.arange(self.N)
+        self.df = GeoDataFrame({"geometry": self.points, "values": values})
+
+    def test_plot(self):
+        # basic test that points with z coords don't break plotting
+        self.df.plot()
+
+
+class TestLineStringPlotting:
+    def setup_method(self):
+        self.N = 10
+        values = np.arange(self.N)
+        self.lines = GeoSeries(
+            [LineString([(0, i), (4, i + 0.5), (9, i)]) for i in 
range(self.N)],
+            index=list("ABCDEFGHIJ"),
+        )
+        self.df = GeoDataFrame({"geometry": self.lines, "values": values})
+
+        multiline1 = MultiLineString(self.lines.loc["A":"B"].values)
+        multiline2 = MultiLineString(self.lines.loc["C":"D"].values)
+        self.df2 = GeoDataFrame(
+            {"geometry": [multiline1, multiline2], "values": [0, 1]}
+        )
+
+        self.linearrings = GeoSeries(
+            [LinearRing([(0, i), (4, i + 0.5), (9, i)]) for i in 
range(self.N)],
+            index=list("ABCDEFGHIJ"),
+        )
+        self.df3 = GeoDataFrame({"geometry": self.linearrings, "values": 
values})
+
+    def test_autolim_false(self):
+        """Test linestring plot preserving axes limits."""
+        ax = self.lines[: self.N // 2].plot()
+        ylim = ax.get_ylim()
+        self.lines.plot(ax=ax, autolim=False)
+        assert ax.get_ylim() == ylim
+        ax = self.df[: self.N // 2].plot()
+        ylim = ax.get_ylim()
+        self.df.plot(ax=ax, autolim=False)
+        assert ax.get_ylim() == ylim
+
+    def test_autolim_true(self):
+        """Test linestring plot autoscaling axes limits."""
+        ax = self.lines[: self.N // 2].plot()
+        ylim = ax.get_ylim()
+        self.lines.plot(ax=ax, autolim=True)
+        assert ax.get_ylim() != ylim
+        ax = self.df[: self.N // 2].plot()
+        ylim = ax.get_ylim()
+        self.df.plot(ax=ax, autolim=True)
+        assert ax.get_ylim() != ylim
+
+    def test_single_color(self):
+        ax = self.lines.plot(color="green")
+        _check_colors(self.N, ax.collections[0].get_colors(), ["green"] * 
self.N)
+
+        ax = self.df.plot(color="green")
+        _check_colors(self.N, ax.collections[0].get_colors(), ["green"] * 
self.N)
+
+        ax = self.linearrings.plot(color="green")
+        _check_colors(self.N, ax.collections[0].get_colors(), ["green"] * 
self.N)
+
+        ax = self.df3.plot(color="green")
+        _check_colors(self.N, ax.collections[0].get_colors(), ["green"] * 
self.N)
+
+        # check rgba tuple GH1178
+        ax = self.df.plot(color=(0.5, 0.5, 0.5, 0.5))
+        _check_colors(
+            self.N, ax.collections[0].get_colors(), [(0.5, 0.5, 0.5, 0.5)] * 
self.N
+        )
+        ax = self.df.plot(color=(0.5, 0.5, 0.5, 0.5))
+        _check_colors(
+            self.N, ax.collections[0].get_colors(), [(0.5, 0.5, 0.5, 0.5)] * 
self.N
+        )
+        with pytest.raises((TypeError, ValueError)):
+            self.df.plot(color="not color")
+
+        with warnings.catch_warnings(record=True) as _:  # don't print warning
+            # 'color' overrides 'column'
+            ax = self.df.plot(column="values", color="green")
+            _check_colors(self.N, ax.collections[0].get_colors(), ["green"] * 
self.N)
+
+    def test_style_kwargs_linestyle(self):
+        # single
+        for ax in [
+            self.lines.plot(linestyle=":", linewidth=1),
+            self.df.plot(linestyle=":", linewidth=1),
+            self.df.plot(column="values", linestyle=":", linewidth=1),
+        ]:
+            assert [(0.0, [1.0, 1.65])] == ax.collections[0].get_linestyle()
+
+        # tuple
+        ax = self.lines.plot(linestyle=(0, (3, 10, 1, 15)), linewidth=1)
+        assert [(0, [3, 10, 1, 15])] == ax.collections[0].get_linestyle()
+
+        # multiple
+        ls = [("dashed", "dotted", "dashdot", "solid")[k % 4] for k in 
range(self.N)]
+        exp_ls = [_style_to_linestring_onoffseq(st, 1) for st in ls]
+        for ax in [
+            self.lines.plot(linestyle=ls, linewidth=1),
+            self.lines.plot(linestyles=ls, linewidth=1),
+            self.df.plot(linestyle=ls, linewidth=1),
+            self.df.plot(column="values", linestyle=ls, linewidth=1),
+        ]:
+            assert exp_ls == ax.collections[0].get_linestyle()
+
+    def test_style_kwargs_linewidth(self):
+        # single
+        for ax in [
+            self.lines.plot(linewidth=2),
+            self.df.plot(linewidth=2),
+            self.df.plot(column="values", linewidth=2),
+        ]:
+            np.testing.assert_array_equal([2], 
ax.collections[0].get_linewidths())
+
+        # multiple
+        lw = [(0, 1, 2, 5.5, 10)[k % 5] for k in range(self.N)]
+        for ax in [
+            self.lines.plot(linewidth=lw),
+            self.lines.plot(linewidths=lw),
+            self.df.plot(linewidth=lw),
+            self.df.plot(column="values", linewidth=lw),
+        ]:
+            np.testing.assert_array_equal(lw, 
ax.collections[0].get_linewidths())
+
+    def test_style_kwargs_alpha(self):
+        ax = self.df.plot(alpha=0.7)
+        np.testing.assert_array_equal([0.7], ax.collections[0].get_alpha())
+        try:
+            ax = self.df.plot(alpha=np.linspace(0, 0.0, 1.0, self.N))

Review Comment:
   Same issue as line 248 - the `np.linspace(0, 0.0, 1.0, self.N)` call appears 
incorrect. It should likely be `np.linspace(0.0, 1.0, self.N)` to create a 
proper alpha range.
   ```suggestion
               ax = self.df.plot(alpha=np.linspace(0.0, 1.0, self.N))
   ```



##########
python/tests/geopandas/test_plotting.py:
##########
@@ -0,0 +1,2086 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# This file is copied from geopandas/tests/test_plotting.py
+# and was modified to skip the tests that require data files.
+
+import itertools
+import warnings
+
+import numpy as np
+import pandas as pd
+
+import pytest
+import shapely
+import geopandas as gpd
+from packaging.version import parse as parse_version
+
+if parse_version(shapely.__version__) < parse_version("2.0.0"):
+    pytest.skip(f"Tests require shapely>=2.0.0", allow_module_level=True)
+
+if parse_version(gpd.__version__) < parse_version("1.0.0"):
+    pytest.skip(f"Tests require geopandas>=1.0.0", allow_module_level=True)
+
+from shapely.affinity import rotate
+from shapely.geometry import (
+    GeometryCollection,
+    LinearRing,
+    LineString,
+    MultiLineString,
+    MultiPoint,
+    MultiPolygon,
+    Point,
+    Polygon,
+    box,
+)
+
+GEOS_GE_390 = True
+HAS_PYPROJ = True
+
+from geopandas import GeoDataFrame, GeoSeries, read_file
+from geopandas.plotting import GeoplotAccessor
+
+matplotlib = pytest.importorskip("matplotlib")
+matplotlib.use("Agg")
+import matplotlib.pyplot as plt
+
+try:  # skipif and importorskip do not work for decorators
+    # Skip these tests in Sedona repo since data is not included in this repo
+    raise ImportError
+    # Original code
+    # from matplotlib.testing.decorators import check_figures_equal, 
image_comparison
+
+    # MPL_DECORATORS = True
+except ImportError:
+    MPL_DECORATORS = False
+
+
[email protected](autouse=True)
+def close_figures(request):
+    yield
+    plt.close("all")
+
+
+try:
+    cycle = matplotlib.rcParams["axes.prop_cycle"].by_key()
+    MPL_DFT_COLOR = cycle["color"][0]
+except KeyError:
+    MPL_DFT_COLOR = matplotlib.rcParams["axes.color_cycle"][0]
+
+plt.rcParams.update({"figure.max_open_warning": 0})
+
+
+class TestPointPlotting:
+    def setup_method(self):
+        self.N = 10
+        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)
+        self.df2 = GeoDataFrame(
+            {"geometry": [multipoint1, multipoint2], "values": [0, 1]}
+        )
+
+    def test_figsize(self):
+        ax = self.points.plot(figsize=(1, 1))
+        np.testing.assert_array_equal(ax.figure.get_size_inches(), (1, 1))
+
+        ax = self.df.plot(figsize=(1, 1))
+        np.testing.assert_array_equal(ax.figure.get_size_inches(), (1, 1))
+
+    def test_default_colors(self):
+        # # without specifying values -> uniform color
+
+        # GeoSeries
+        ax = self.points.plot()
+        _check_colors(
+            self.N, ax.collections[0].get_facecolors(), [MPL_DFT_COLOR] * 
self.N
+        )
+
+        # GeoDataFrame
+        ax = self.df.plot()
+        _check_colors(
+            self.N, ax.collections[0].get_facecolors(), [MPL_DFT_COLOR] * 
self.N
+        )
+
+        # # with specifying values -> different colors for all 10 values
+        ax = self.df.plot(column="values")
+        cmap = plt.get_cmap()
+        expected_colors = cmap(np.arange(self.N) / (self.N - 1))
+        _check_colors(self.N, ax.collections[0].get_facecolors(), 
expected_colors)
+
+    def test_series_color_no_index(self):
+        # Color order with ordered index
+        colors_ord = pd.Series(["a", "b", "c", "a", "b", "c", "a", "b", "c", 
"a"])
+
+        # Plot using Series as color
+        ax1 = self.df.plot(colors_ord)
+
+        # Correct answer: Add as column to df and plot
+        self.df["colors_ord"] = colors_ord
+        ax2 = self.df.plot("colors_ord")
+
+        # Confirm out-of-order index re-sorted
+        point_colors1 = ax1.collections[0].get_facecolors()
+        point_colors2 = ax2.collections[0].get_facecolors()
+        np.testing.assert_array_equal(point_colors1[1], point_colors2[1])
+
+    def test_series_color_index(self):
+        # Color order with out-of-order index
+        colors_ord = pd.Series(
+            ["a", "a", "a", "a", "b", "b", "b", "c", "c", "c"],
+            index=[0, 3, 6, 9, 1, 4, 7, 2, 5, 8],
+        )
+
+        # Plot using Series as color
+        ax1 = self.df.plot(colors_ord)
+
+        # Correct answer: Add as column to df and plot
+        self.df["colors_ord"] = colors_ord
+        ax2 = self.df.plot("colors_ord")
+
+        # Confirm out-of-order index re-sorted
+        point_colors1 = ax1.collections[0].get_facecolors()
+        point_colors2 = ax2.collections[0].get_facecolors()
+        np.testing.assert_array_equal(point_colors1[1], point_colors2[1])
+
+    def test_colormap(self):
+        # without specifying values but cmap specified -> no uniform color
+        # but different colors for all points
+
+        # GeoSeries
+        ax = self.points.plot(cmap="RdYlGn")
+        cmap = plt.get_cmap("RdYlGn")
+        exp_colors = cmap(np.arange(self.N) / (self.N - 1))
+        _check_colors(self.N, ax.collections[0].get_facecolors(), exp_colors)
+
+        ax = self.df.plot(cmap="RdYlGn")
+        _check_colors(self.N, ax.collections[0].get_facecolors(), exp_colors)
+
+        # # with specifying values -> different colors for all 10 values
+        ax = self.df.plot(column="values", cmap="RdYlGn")
+        cmap = plt.get_cmap("RdYlGn")
+        _check_colors(self.N, ax.collections[0].get_facecolors(), exp_colors)
+
+        # when using a cmap with specified lut -> limited number of different
+        # colors
+        ax = self.points.plot(cmap=plt.get_cmap("Set1", lut=5))
+        cmap = plt.get_cmap("Set1", lut=5)
+        exp_colors = cmap(list(range(5)) * 2)
+        _check_colors(self.N, ax.collections[0].get_facecolors(), exp_colors)
+
+    def test_single_color(self):
+        ax = self.points.plot(color="green")
+        _check_colors(self.N, ax.collections[0].get_facecolors(), ["green"] * 
self.N)
+
+        ax = self.df.plot(color="green")
+        _check_colors(self.N, ax.collections[0].get_facecolors(), ["green"] * 
self.N)
+
+        # check rgba tuple GH1178
+        ax = self.df.plot(color=(0.5, 0.5, 0.5))
+        _check_colors(
+            self.N, ax.collections[0].get_facecolors(), [(0.5, 0.5, 0.5)] * 
self.N
+        )
+        ax = self.df.plot(color=(0.5, 0.5, 0.5, 0.5))
+        _check_colors(
+            self.N, ax.collections[0].get_facecolors(), [(0.5, 0.5, 0.5, 0.5)] 
* self.N
+        )
+        with pytest.raises((ValueError, TypeError)):
+            self.df.plot(color="not color")
+
+        with warnings.catch_warnings(record=True) as _:  # don't print warning
+            # 'color' overrides 'column'
+            ax = self.df.plot(column="values", color="green")
+            _check_colors(
+                self.N, ax.collections[0].get_facecolors(), ["green"] * self.N
+            )
+
+    def test_markersize(self):
+        ax = self.points.plot(markersize=10)
+        assert ax.collections[0].get_sizes() == [10]
+
+        ax = self.df.plot(markersize=10)
+        assert ax.collections[0].get_sizes() == [10]
+
+        ax = self.df.plot(column="values", markersize=10)
+        assert ax.collections[0].get_sizes() == [10]
+
+        ax = self.df.plot(markersize="values")
+        assert (ax.collections[0].get_sizes() == self.df["values"]).all()
+
+        ax = self.df.plot(column="values", markersize="values")
+        assert (ax.collections[0].get_sizes() == self.df["values"]).all()
+
+    def test_markerstyle(self):
+        ax = self.df2.plot(marker="+")
+        expected = _style_to_vertices("+")
+        np.testing.assert_array_equal(
+            expected, ax.collections[0].get_paths()[0].vertices
+        )
+
+    def test_style_kwargs(self):
+        ax = self.points.plot(edgecolors="k")
+        assert (ax.collections[0].get_edgecolor() == [0, 0, 0, 1]).all()
+
+    def test_style_kwargs_alpha(self):
+        ax = self.df.plot(alpha=0.7)
+        np.testing.assert_array_equal([0.7], ax.collections[0].get_alpha())
+        try:
+            ax = self.df.plot(alpha=np.linspace(0, 0.0, 1.0, self.N))
+        except TypeError:
+            # no list allowed for alpha up to matplotlib 3.3
+            pass
+        else:
+            np.testing.assert_array_equal(
+                np.linspace(0, 0.0, 1.0, self.N), ax.collections[0].get_alpha()

Review Comment:
   The `np.linspace(0, 0.0, 1.0, self.N)` call appears incorrect - it should 
likely be `np.linspace(0.0, 1.0, self.N)` to create a proper range from 0 to 1, 
rather than from 0 to 0.0 with an unexpected third parameter.
   ```suggestion
               ax = self.df.plot(alpha=np.linspace(0.0, 1.0, self.N))
           except TypeError:
               # no list allowed for alpha up to matplotlib 3.3
               pass
           else:
               np.testing.assert_array_equal(
                   np.linspace(0.0, 1.0, self.N), ax.collections[0].get_alpha()
   ```



##########
python/tests/geopandas/test_plotting.py:
##########
@@ -0,0 +1,2086 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# This file is copied from geopandas/tests/test_plotting.py
+# and was modified to skip the tests that require data files.
+
+import itertools
+import warnings
+
+import numpy as np
+import pandas as pd
+
+import pytest
+import shapely
+import geopandas as gpd
+from packaging.version import parse as parse_version
+
+if parse_version(shapely.__version__) < parse_version("2.0.0"):
+    pytest.skip(f"Tests require shapely>=2.0.0", allow_module_level=True)
+
+if parse_version(gpd.__version__) < parse_version("1.0.0"):
+    pytest.skip(f"Tests require geopandas>=1.0.0", allow_module_level=True)
+
+from shapely.affinity import rotate
+from shapely.geometry import (
+    GeometryCollection,
+    LinearRing,
+    LineString,
+    MultiLineString,
+    MultiPoint,
+    MultiPolygon,
+    Point,
+    Polygon,
+    box,
+)
+
+GEOS_GE_390 = True
+HAS_PYPROJ = True
+
+from geopandas import GeoDataFrame, GeoSeries, read_file
+from geopandas.plotting import GeoplotAccessor
+
+matplotlib = pytest.importorskip("matplotlib")
+matplotlib.use("Agg")
+import matplotlib.pyplot as plt
+
+try:  # skipif and importorskip do not work for decorators
+    # Skip these tests in Sedona repo since data is not included in this repo
+    raise ImportError
+    # Original code
+    # from matplotlib.testing.decorators import check_figures_equal, 
image_comparison
+
+    # MPL_DECORATORS = True
+except ImportError:
+    MPL_DECORATORS = False
+
+
[email protected](autouse=True)
+def close_figures(request):
+    yield
+    plt.close("all")
+
+
+try:
+    cycle = matplotlib.rcParams["axes.prop_cycle"].by_key()
+    MPL_DFT_COLOR = cycle["color"][0]
+except KeyError:
+    MPL_DFT_COLOR = matplotlib.rcParams["axes.color_cycle"][0]
+
+plt.rcParams.update({"figure.max_open_warning": 0})
+
+
+class TestPointPlotting:
+    def setup_method(self):
+        self.N = 10
+        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)
+        self.df2 = GeoDataFrame(
+            {"geometry": [multipoint1, multipoint2], "values": [0, 1]}
+        )
+
+    def test_figsize(self):
+        ax = self.points.plot(figsize=(1, 1))
+        np.testing.assert_array_equal(ax.figure.get_size_inches(), (1, 1))
+
+        ax = self.df.plot(figsize=(1, 1))
+        np.testing.assert_array_equal(ax.figure.get_size_inches(), (1, 1))
+
+    def test_default_colors(self):
+        # # without specifying values -> uniform color
+
+        # GeoSeries
+        ax = self.points.plot()
+        _check_colors(
+            self.N, ax.collections[0].get_facecolors(), [MPL_DFT_COLOR] * 
self.N
+        )
+
+        # GeoDataFrame
+        ax = self.df.plot()
+        _check_colors(
+            self.N, ax.collections[0].get_facecolors(), [MPL_DFT_COLOR] * 
self.N
+        )
+
+        # # with specifying values -> different colors for all 10 values
+        ax = self.df.plot(column="values")
+        cmap = plt.get_cmap()
+        expected_colors = cmap(np.arange(self.N) / (self.N - 1))
+        _check_colors(self.N, ax.collections[0].get_facecolors(), 
expected_colors)
+
+    def test_series_color_no_index(self):
+        # Color order with ordered index
+        colors_ord = pd.Series(["a", "b", "c", "a", "b", "c", "a", "b", "c", 
"a"])
+
+        # Plot using Series as color
+        ax1 = self.df.plot(colors_ord)
+
+        # Correct answer: Add as column to df and plot
+        self.df["colors_ord"] = colors_ord
+        ax2 = self.df.plot("colors_ord")
+
+        # Confirm out-of-order index re-sorted
+        point_colors1 = ax1.collections[0].get_facecolors()
+        point_colors2 = ax2.collections[0].get_facecolors()
+        np.testing.assert_array_equal(point_colors1[1], point_colors2[1])
+
+    def test_series_color_index(self):
+        # Color order with out-of-order index
+        colors_ord = pd.Series(
+            ["a", "a", "a", "a", "b", "b", "b", "c", "c", "c"],
+            index=[0, 3, 6, 9, 1, 4, 7, 2, 5, 8],
+        )
+
+        # Plot using Series as color
+        ax1 = self.df.plot(colors_ord)
+
+        # Correct answer: Add as column to df and plot
+        self.df["colors_ord"] = colors_ord
+        ax2 = self.df.plot("colors_ord")
+
+        # Confirm out-of-order index re-sorted
+        point_colors1 = ax1.collections[0].get_facecolors()
+        point_colors2 = ax2.collections[0].get_facecolors()
+        np.testing.assert_array_equal(point_colors1[1], point_colors2[1])
+
+    def test_colormap(self):
+        # without specifying values but cmap specified -> no uniform color
+        # but different colors for all points
+
+        # GeoSeries
+        ax = self.points.plot(cmap="RdYlGn")
+        cmap = plt.get_cmap("RdYlGn")
+        exp_colors = cmap(np.arange(self.N) / (self.N - 1))
+        _check_colors(self.N, ax.collections[0].get_facecolors(), exp_colors)
+
+        ax = self.df.plot(cmap="RdYlGn")
+        _check_colors(self.N, ax.collections[0].get_facecolors(), exp_colors)
+
+        # # with specifying values -> different colors for all 10 values
+        ax = self.df.plot(column="values", cmap="RdYlGn")
+        cmap = plt.get_cmap("RdYlGn")
+        _check_colors(self.N, ax.collections[0].get_facecolors(), exp_colors)
+
+        # when using a cmap with specified lut -> limited number of different
+        # colors
+        ax = self.points.plot(cmap=plt.get_cmap("Set1", lut=5))
+        cmap = plt.get_cmap("Set1", lut=5)
+        exp_colors = cmap(list(range(5)) * 2)
+        _check_colors(self.N, ax.collections[0].get_facecolors(), exp_colors)
+
+    def test_single_color(self):
+        ax = self.points.plot(color="green")
+        _check_colors(self.N, ax.collections[0].get_facecolors(), ["green"] * 
self.N)
+
+        ax = self.df.plot(color="green")
+        _check_colors(self.N, ax.collections[0].get_facecolors(), ["green"] * 
self.N)
+
+        # check rgba tuple GH1178
+        ax = self.df.plot(color=(0.5, 0.5, 0.5))
+        _check_colors(
+            self.N, ax.collections[0].get_facecolors(), [(0.5, 0.5, 0.5)] * 
self.N
+        )
+        ax = self.df.plot(color=(0.5, 0.5, 0.5, 0.5))
+        _check_colors(
+            self.N, ax.collections[0].get_facecolors(), [(0.5, 0.5, 0.5, 0.5)] 
* self.N
+        )
+        with pytest.raises((ValueError, TypeError)):
+            self.df.plot(color="not color")
+
+        with warnings.catch_warnings(record=True) as _:  # don't print warning
+            # 'color' overrides 'column'
+            ax = self.df.plot(column="values", color="green")
+            _check_colors(
+                self.N, ax.collections[0].get_facecolors(), ["green"] * self.N
+            )
+
+    def test_markersize(self):
+        ax = self.points.plot(markersize=10)
+        assert ax.collections[0].get_sizes() == [10]
+
+        ax = self.df.plot(markersize=10)
+        assert ax.collections[0].get_sizes() == [10]
+
+        ax = self.df.plot(column="values", markersize=10)
+        assert ax.collections[0].get_sizes() == [10]
+
+        ax = self.df.plot(markersize="values")
+        assert (ax.collections[0].get_sizes() == self.df["values"]).all()
+
+        ax = self.df.plot(column="values", markersize="values")
+        assert (ax.collections[0].get_sizes() == self.df["values"]).all()
+
+    def test_markerstyle(self):
+        ax = self.df2.plot(marker="+")
+        expected = _style_to_vertices("+")
+        np.testing.assert_array_equal(
+            expected, ax.collections[0].get_paths()[0].vertices
+        )
+
+    def test_style_kwargs(self):
+        ax = self.points.plot(edgecolors="k")
+        assert (ax.collections[0].get_edgecolor() == [0, 0, 0, 1]).all()
+
+    def test_style_kwargs_alpha(self):
+        ax = self.df.plot(alpha=0.7)
+        np.testing.assert_array_equal([0.7], ax.collections[0].get_alpha())
+        try:
+            ax = self.df.plot(alpha=np.linspace(0, 0.0, 1.0, self.N))
+        except TypeError:
+            # no list allowed for alpha up to matplotlib 3.3
+            pass
+        else:
+            np.testing.assert_array_equal(
+                np.linspace(0, 0.0, 1.0, self.N), ax.collections[0].get_alpha()
+            )
+
+    def test_legend(self):
+        with warnings.catch_warnings(record=True) as _:  # don't print warning
+            # legend ignored if color is given.
+            ax = self.df.plot(column="values", color="green", legend=True)
+            assert len(ax.get_figure().axes) == 1  # no separate legend axis
+
+        # legend ignored if no column is given.
+        ax = self.df.plot(legend=True)
+        assert len(ax.get_figure().axes) == 1  # no separate legend axis
+
+        # # Continuous legend
+        # the colorbar matches the Point colors
+        ax = self.df.plot(column="values", cmap="RdYlGn", legend=True)
+        point_colors = ax.collections[0].get_facecolors()
+        cbar_colors = 
_get_colorbar_ax(ax.get_figure()).collections[-1].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])
+
+        # # Categorical legend
+        # the colorbar matches the Point colors
+        ax = self.df.plot(column="values", categorical=True, legend=True)
+        point_colors = ax.collections[0].get_facecolors()
+        cbar_colors = ax.get_legend().axes.collections[-1].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])
+
+        # # 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 = 
_get_colorbar_ax(ax.get_figure()).collections[-1].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
+        norm = matplotlib.colors.Normalize(vmin=0, vmax=20)
+        ax = self.df.plot(column="values", cmap=cmap, norm=norm)
+        actual_colors_orig = ax.collections[0].get_facecolors()
+        exp_colors = cmap(np.arange(10) / (20))
+        np.testing.assert_array_equal(exp_colors, actual_colors_orig)
+        fig, ax = plt.subplots()
+        self.df[1:].plot(column="values", ax=ax, norm=norm, cmap=cmap)
+        actual_colors_sub = ax.collections[0].get_facecolors()
+        np.testing.assert_array_equal(actual_colors_orig[1], 
actual_colors_sub[0])
+
+    def test_empty_plot(self):
+        s = GeoSeries([Polygon()])
+        with pytest.warns(UserWarning):
+            ax = s.plot()
+        assert len(ax.collections) == 0
+        s = GeoSeries([])
+        with pytest.warns(UserWarning):
+            ax = s.plot()
+        assert len(ax.collections) == 0
+        df = GeoDataFrame([], columns=["geometry"])
+        with pytest.warns(UserWarning):
+            ax = df.plot()
+        assert len(ax.collections) == 0
+
+    def test_empty_geometry(self):
+        s = GeoSeries([Polygon([(0, 0), (1, 0), (1, 1)]), Polygon()])
+        ax = s.plot()
+        assert len(ax.collections) == 1
+
+        # more complex case with GEOMETRYCOLLECTION EMPTY, POINT EMPTY and NONE
+        poly = Polygon([(-1, -1), (-1, 2), (2, 2), (2, -1), (-1, -1)])
+        point = Point(0, 1)
+        point_ = Point(10, 10)
+        empty_point = Point()
+
+        gdf = GeoDataFrame(geometry=[point, empty_point, point_])
+        gdf["geometry"] = gdf.intersection(poly)
+        with warnings.catch_warnings():
+            # loc to add row calls concat internally, warning for pandas >=2.1
+            warnings.filterwarnings(
+                "ignore",
+                "The behavior of DataFrame concatenation with empty",
+                FutureWarning,
+            )
+            gdf.loc[3] = [None]
+        ax = gdf.plot()
+        assert len(ax.collections) == 1
+
+    @pytest.mark.parametrize(
+        "geoms",
+        [
+            [
+                box(0, 0, 1, 1),
+                box(7, 7, 8, 8),
+            ],
+            [
+                LineString([(1, 1), (1, 2)]),
+                LineString([(7, 1), (7, 2)]),
+            ],
+            [
+                Point(1, 1),
+                Point(7, 7),
+            ],
+        ],
+    )
+    def test_empty_geometry_colors(self, geoms):
+        s = GeoSeries(
+            geoms,
+            index=["r", "b"],
+        )
+        s2 = s.intersection(box(5, 0, 10, 10))
+        ax = s2.plot(color=["red", "blue"])
+        blue = np.array([0.0, 0.0, 1.0, 1.0])
+        if s.geom_type["r"] == "LineString":
+            
np.testing.assert_array_equal(ax.get_children()[0].get_edgecolor()[0], blue)
+        else:
+            
np.testing.assert_array_equal(ax.get_children()[0].get_facecolor()[0], blue)
+
+    def test_multipoints(self):
+        # MultiPoints
+        ax = self.df2.plot()
+        _check_colors(4, ax.collections[0].get_facecolors(), [MPL_DFT_COLOR] * 
4)
+
+        ax = self.df2.plot(column="values")
+        cmap = plt.get_cmap(lut=2)
+        expected_colors = [cmap(0)] * self.N + [cmap(1)] * self.N
+        _check_colors(20, ax.collections[0].get_facecolors(), expected_colors)
+
+        ax = self.df2.plot(color=["r", "b"])
+        # colors are repeated for all components within a MultiPolygon
+        _check_colors(20, ax.collections[0].get_facecolors(), ["r"] * 10 + 
["b"] * 10)
+
+    def test_multipoints_alpha(self):
+        ax = self.df2.plot(alpha=0.7)
+        np.testing.assert_array_equal([0.7], ax.collections[0].get_alpha())
+        try:
+            ax = self.df2.plot(alpha=[0.7, 0.2])
+        except TypeError:
+            # no list allowed for alpha up to matplotlib 3.3
+            pass
+        else:
+            np.testing.assert_array_equal(
+                [0.7] * 10 + [0.2] * 10, ax.collections[0].get_alpha()
+            )
+
+    def test_categories(self):
+        self.df["cats_object"] = ["cat1", "cat2"] * 5
+        self.df["nums"] = [1, 2] * 5
+        self.df["singlecat_object"] = ["cat2"] * 10
+        self.df["cats"] = pd.Categorical(["cat1", "cat2"] * 5)
+        self.df["singlecat"] = pd.Categorical(
+            ["cat2"] * 10, categories=["cat1", "cat2"]
+        )
+        self.df["cats_ordered"] = pd.Categorical(
+            ["cat2", "cat1"] * 5, categories=["cat2", "cat1"]
+        )
+        self.df["bool"] = [False, True] * 5
+        self.df["bool_extension"] = pd.array([False, True] * 5)
+        self.df["cats_string"] = pd.array(["cat1", "cat2"] * 5, dtype="string")
+
+        ax1 = self.df.plot("cats_object", legend=True)
+        ax2 = self.df.plot("cats", legend=True)
+        ax3 = self.df.plot("singlecat_object", categories=["cat1", "cat2"], 
legend=True)
+        ax4 = self.df.plot("singlecat", legend=True)
+        ax5 = self.df.plot("cats_ordered", legend=True)
+        ax6 = self.df.plot("nums", categories=[1, 2], legend=True)
+        ax7 = self.df.plot("bool", legend=True)
+        ax8 = self.df.plot("bool_extension", legend=True)
+        ax9 = self.df.plot("cats_string", legend=True)
+
+        point_colors1 = ax1.collections[0].get_facecolors()
+        for ax in [ax2, ax3, ax4, ax5, ax6, ax7, ax8, ax9]:
+            point_colors2 = ax.collections[0].get_facecolors()
+            np.testing.assert_array_equal(point_colors1[1], point_colors2[1])
+
+        legend1 = [x.get_markerfacecolor() for x in 
ax1.get_legend().get_lines()]
+        for ax in [ax2, ax3, ax4, ax5, ax6, ax7, ax8, ax9]:
+            legend2 = [x.get_markerfacecolor() for x in 
ax.get_legend().get_lines()]
+            np.testing.assert_array_equal(legend1, legend2)
+
+        with pytest.raises(TypeError):
+            self.df.plot(column="cats_object", categories="non_list")
+
+        with pytest.raises(
+            ValueError, match="Column contains values not listed in 
categories."
+        ):
+            self.df.plot(column="cats_object", categories=["cat1"])
+
+        with pytest.raises(
+            ValueError, match="Cannot specify 'categories' when column has"
+        ):
+            self.df.plot(column="cats", categories=["cat1"])
+
+    def test_missing(self):
+        self.df.loc[0, "values"] = np.nan
+        ax = self.df.plot("values")
+        cmap = plt.get_cmap()
+        expected_colors = cmap(np.arange(self.N - 1) / (self.N - 2))
+        _check_colors(self.N - 1, ax.collections[0].get_facecolors(), 
expected_colors)
+
+        ax = self.df.plot("values", missing_kwds={"color": "r"})
+        cmap = plt.get_cmap()
+        expected_colors = cmap(np.arange(self.N - 1) / (self.N - 2))
+        _check_colors(1, ax.collections[1].get_facecolors(), ["r"])
+        _check_colors(self.N - 1, ax.collections[0].get_facecolors(), 
expected_colors)
+
+        ax = self.df.plot(
+            "values", missing_kwds={"color": "r"}, categorical=True, 
legend=True
+        )
+        _check_colors(1, ax.collections[1].get_facecolors(), ["r"])
+        point_colors = ax.collections[0].get_facecolors()
+        nan_color = ax.collections[1].get_facecolors()
+        leg_colors = ax.get_legend().axes.collections[0].get_facecolors()
+        leg_colors1 = ax.get_legend().axes.collections[1].get_facecolors()
+        np.testing.assert_array_equal(point_colors[0], leg_colors[0])
+        np.testing.assert_array_equal(nan_color[0], leg_colors1[0])
+
+    def test_no_missing_and_missing_kwds(self):
+        # GH2210
+        df = self.df.copy()
+        df["category"] = df["values"].astype("str")
+        df.plot("category", missing_kwds={"facecolor": "none"}, legend=True)
+
+    @pytest.mark.skip(reason="failing on older versions for uninvestigated 
reasons")
+    def test_missing_aspect(self):
+        self.df.loc[0, "values"] = np.nan
+        ax = self.df.plot(
+            "values",
+            missing_kwds={"color": "r"},
+            categorical=True,
+            legend=True,
+            aspect=2,
+        )
+        assert ax.get_aspect() == 2
+
+
+class TestPointZPlotting:
+    def setup_method(self):
+        self.N = 10
+        self.points = GeoSeries(Point(i, i, i) for i in range(self.N))
+        values = np.arange(self.N)
+        self.df = GeoDataFrame({"geometry": self.points, "values": values})
+
+    def test_plot(self):
+        # basic test that points with z coords don't break plotting
+        self.df.plot()
+
+
+class TestLineStringPlotting:
+    def setup_method(self):
+        self.N = 10
+        values = np.arange(self.N)
+        self.lines = GeoSeries(
+            [LineString([(0, i), (4, i + 0.5), (9, i)]) for i in 
range(self.N)],
+            index=list("ABCDEFGHIJ"),
+        )
+        self.df = GeoDataFrame({"geometry": self.lines, "values": values})
+
+        multiline1 = MultiLineString(self.lines.loc["A":"B"].values)
+        multiline2 = MultiLineString(self.lines.loc["C":"D"].values)
+        self.df2 = GeoDataFrame(
+            {"geometry": [multiline1, multiline2], "values": [0, 1]}
+        )
+
+        self.linearrings = GeoSeries(
+            [LinearRing([(0, i), (4, i + 0.5), (9, i)]) for i in 
range(self.N)],
+            index=list("ABCDEFGHIJ"),
+        )
+        self.df3 = GeoDataFrame({"geometry": self.linearrings, "values": 
values})
+
+    def test_autolim_false(self):
+        """Test linestring plot preserving axes limits."""
+        ax = self.lines[: self.N // 2].plot()
+        ylim = ax.get_ylim()
+        self.lines.plot(ax=ax, autolim=False)
+        assert ax.get_ylim() == ylim
+        ax = self.df[: self.N // 2].plot()
+        ylim = ax.get_ylim()
+        self.df.plot(ax=ax, autolim=False)
+        assert ax.get_ylim() == ylim
+
+    def test_autolim_true(self):
+        """Test linestring plot autoscaling axes limits."""
+        ax = self.lines[: self.N // 2].plot()
+        ylim = ax.get_ylim()
+        self.lines.plot(ax=ax, autolim=True)
+        assert ax.get_ylim() != ylim
+        ax = self.df[: self.N // 2].plot()
+        ylim = ax.get_ylim()
+        self.df.plot(ax=ax, autolim=True)
+        assert ax.get_ylim() != ylim
+
+    def test_single_color(self):
+        ax = self.lines.plot(color="green")
+        _check_colors(self.N, ax.collections[0].get_colors(), ["green"] * 
self.N)
+
+        ax = self.df.plot(color="green")
+        _check_colors(self.N, ax.collections[0].get_colors(), ["green"] * 
self.N)
+
+        ax = self.linearrings.plot(color="green")
+        _check_colors(self.N, ax.collections[0].get_colors(), ["green"] * 
self.N)
+
+        ax = self.df3.plot(color="green")
+        _check_colors(self.N, ax.collections[0].get_colors(), ["green"] * 
self.N)
+
+        # check rgba tuple GH1178
+        ax = self.df.plot(color=(0.5, 0.5, 0.5, 0.5))
+        _check_colors(
+            self.N, ax.collections[0].get_colors(), [(0.5, 0.5, 0.5, 0.5)] * 
self.N
+        )
+        ax = self.df.plot(color=(0.5, 0.5, 0.5, 0.5))
+        _check_colors(
+            self.N, ax.collections[0].get_colors(), [(0.5, 0.5, 0.5, 0.5)] * 
self.N
+        )
+        with pytest.raises((TypeError, ValueError)):
+            self.df.plot(color="not color")
+
+        with warnings.catch_warnings(record=True) as _:  # don't print warning
+            # 'color' overrides 'column'
+            ax = self.df.plot(column="values", color="green")
+            _check_colors(self.N, ax.collections[0].get_colors(), ["green"] * 
self.N)
+
+    def test_style_kwargs_linestyle(self):
+        # single
+        for ax in [
+            self.lines.plot(linestyle=":", linewidth=1),
+            self.df.plot(linestyle=":", linewidth=1),
+            self.df.plot(column="values", linestyle=":", linewidth=1),
+        ]:
+            assert [(0.0, [1.0, 1.65])] == ax.collections[0].get_linestyle()
+
+        # tuple
+        ax = self.lines.plot(linestyle=(0, (3, 10, 1, 15)), linewidth=1)
+        assert [(0, [3, 10, 1, 15])] == ax.collections[0].get_linestyle()
+
+        # multiple
+        ls = [("dashed", "dotted", "dashdot", "solid")[k % 4] for k in 
range(self.N)]
+        exp_ls = [_style_to_linestring_onoffseq(st, 1) for st in ls]
+        for ax in [
+            self.lines.plot(linestyle=ls, linewidth=1),
+            self.lines.plot(linestyles=ls, linewidth=1),
+            self.df.plot(linestyle=ls, linewidth=1),
+            self.df.plot(column="values", linestyle=ls, linewidth=1),
+        ]:
+            assert exp_ls == ax.collections[0].get_linestyle()
+
+    def test_style_kwargs_linewidth(self):
+        # single
+        for ax in [
+            self.lines.plot(linewidth=2),
+            self.df.plot(linewidth=2),
+            self.df.plot(column="values", linewidth=2),
+        ]:
+            np.testing.assert_array_equal([2], 
ax.collections[0].get_linewidths())
+
+        # multiple
+        lw = [(0, 1, 2, 5.5, 10)[k % 5] for k in range(self.N)]
+        for ax in [
+            self.lines.plot(linewidth=lw),
+            self.lines.plot(linewidths=lw),
+            self.df.plot(linewidth=lw),
+            self.df.plot(column="values", linewidth=lw),
+        ]:
+            np.testing.assert_array_equal(lw, 
ax.collections[0].get_linewidths())
+
+    def test_style_kwargs_alpha(self):
+        ax = self.df.plot(alpha=0.7)
+        np.testing.assert_array_equal([0.7], ax.collections[0].get_alpha())
+        try:
+            ax = self.df.plot(alpha=np.linspace(0, 0.0, 1.0, self.N))
+        except TypeError:
+            # no list allowed for alpha up to matplotlib 3.3
+            pass
+        else:
+            np.testing.assert_array_equal(
+                np.linspace(0, 0.0, 1.0, self.N), ax.collections[0].get_alpha()

Review Comment:
   Consistent with the previous issues - this `np.linspace(0, 0.0, 1.0, 
self.N)` call should likely be `np.linspace(0.0, 1.0, self.N)` to match the 
expected alpha values.
   ```suggestion
               ax = self.df.plot(alpha=np.linspace(0.0, 1.0, self.N))
           except TypeError:
               # no list allowed for alpha up to matplotlib 3.3
               pass
           else:
               np.testing.assert_array_equal(
                   np.linspace(0.0, 1.0, self.N), ax.collections[0].get_alpha()
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to