martinfleis: Nice! Pandas 0.23 does not like it but considering we will not support it for much longer, I think that it is fine as it is.
diff --git a/geopandas/plotting.py b/geopandas/plotting.py
index 169fe39d..9fef122c 100644
--- a/geopandas/plotting.py
+++ b/geopandas/plotting.py
@@ -619,44 +619,40 @@ def plot_dataframe(
                 "The dataframe and given column have different number of rows."
             )
         else:
-            values = np.asarray(column)
+            values = column
     else:
-        values = np.asarray(df[column])
+        values = df[column]
 
-    if values.dtype is np.dtype("O"):
+    if pd.api.types.is_categorical_dtype(values.dtype):
+        if categories is not None:
+            raise ValueError(
+                "Cannot specify 'categories' when column has categorical dtype"
+            )
         categorical = True
-
-    nan_idx = pd.isna(values)
-
-    if categories:
+    elif values.dtype is np.dtype("O") or categories:
         categorical = True
 
+    nan_idx = np.asarray(pd.isna(values), dtype="bool")
+
     # Define `values` as a Series
     if categorical:
         if cmap is None:
             cmap = "tab10"
 
-        if categories is None:
-            categories = list(set(values[~nan_idx]))
-            categories.sort()
-        else:
-            if not pd.api.types.is_list_like(categories):
-                raise ValueError(
-                    "Categories must be a list-like object. Objects that are "
-                    "considered list-like are for example Python lists, tuples, sets, "
-                    "NumPy arrays, and Pandas Series."
-                )
-            missing = [x for x in values[~nan_idx] if x not in categories]
-            if missing:
-                raise ValueError(
-                    "Column contains values not listed in categories. "
-                    "Missing categories: {}.".format(missing)
-                )
+        cat = pd.Categorical(values, categories=categories)
+        categories = list(cat.categories)
+
+        # values missing in the Categorical but not in original values
+        missing = list(np.unique(values[~nan_idx & cat.isna()]))
+        if missing:
+            raise ValueError(
+                "Column contains values not listed in categories. "
+                "Missing categories: {}.".format(missing)
+            )
 
-        valuemap = dict((k, v) for (v, k) in enumerate(categories))
-        values = np.array([valuemap[k] for k in values[~nan_idx]])
+        values = cat.codes[~nan_idx]
         vmin = 0 if vmin is None else vmin
-        vmax = max(valuemap.values()) if vmax is None else vmax
+        vmax = len(categories) - 1 if vmax is None else vmax
 
     if scheme is not None:
         if classification_kwds is None:

Legend of GeoDataFrame does not sort categorical data values
I try to plot a map of temperature with geopandas in Google Colaboratory. This is my dataset:
```

id = '1LOywA8JPP6vOFDP-CBOBgkSmX7zv2pDc'

downloaded = drive.CreateFile({'id':id}) 
downloaded.GetContentFile('temp_zone.geojson')
print('The files was downloaded')

temp_zone = gpd.read_file('temp_zone.geojson')
print(temp_zone.rango.unique())
temp_zone.head()
```
And this is the output:
![image](https://user-images.githubusercontent.com/40966420/66720955-c3c12280-edc7-11e9-812f-14432eb67829.png)

How you can see when I print the column of "rango", this have not any order, so I will sort as I want:

```
ordered_temp = [ '< 8', '8 - 12', '12 - 16','16 - 20', '20 - 22', '22 - 24','24 - 26','26 - 28', '> 28' ]
temp_zone['rango'] = temp_zone.rango.astype('category',
                                        ordered=True,
                                        categories=ordered_temp)
print(temp_zone.rango.unique())
```

Finally, when I try to plot the map, the values in the legend are not sorted as wrote before in the categorical data, because the value '<8' is near the last position when this should be in the first position. The image is something like this:

![image](https://user-images.githubusercontent.com/40966420/66720993-ebb08600-edc7-11e9-9fcf-11c21b8dba46.png)


Anyone does know how to fix it?
diff --git a/geopandas/tests/test_plotting.py b/geopandas/tests/test_plotting.py
index 2dec35ed..88e50f70 100644
--- a/geopandas/tests/test_plotting.py
+++ b/geopandas/tests/test_plotting.py
@@ -2,6 +2,7 @@ import itertools
 import warnings
 
 import numpy as np
+import pandas as pd
 
 from shapely.affinity import rotate
 from shapely.geometry import (
@@ -262,30 +263,45 @@ class TestPointPlotting:
         with pytest.raises(TypeError):  # no list allowed for alpha
             ax = self.df2.plot(alpha=[0.7, 0.2])
 
-    def test_categorical_list(self):
-        self.df["cats"] = ["cat1", "cat2"] * 5
+    def test_categories(self):
+        self.df["cats_object"] = ["cat1", "cat2"] * 5
         self.df["nums"] = [1, 2] * 5
-        self.df["singlecat"] = ["cat2"] * 10
-        ax1 = self.df.plot("cats", legend=True)
-        ax2 = self.df.plot("singlecat", categories=["cat1", "cat2"], legend=True)
-        ax3 = self.df.plot("nums", categories=[1, 2], legend=True)
-        point_colors1 = ax1.collections[0].get_facecolors()
-        point_colors2 = ax2.collections[0].get_facecolors()
-        point_colors3 = ax3.collections[0].get_facecolors()
-        np.testing.assert_array_equal(
-            point_colors1[1], point_colors2[0], point_colors3[0]
+        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"]
         )
+
+        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)
+
+        point_colors1 = ax1.collections[0].get_facecolors()
+        for ax in [ax2, ax3, ax4, ax5, ax6]:
+            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()]
-        legend2 = [x.get_markerfacecolor() for x in ax2.get_legend().get_lines()]
-        legend3 = [x.get_markerfacecolor() for x in ax3.get_legend().get_lines()]
-        np.testing.assert_array_equal(legend1, legend2)
-        np.testing.assert_array_equal(legend1, legend3)
+        for ax in [ax2, ax3, ax4, ax5, ax6]:
+            legend2 = [x.get_markerfacecolor() for x in ax.get_legend().get_lines()]
+            np.testing.assert_array_equal(legend1, legend2)
 
-        with pytest.raises(ValueError, match="Categories must be a list-like object."):
-            self.df.plot(column="cats", categories="non_list")
+        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"])
 

pip install -e .
parse_log_pytest
requirements.txt
pytest descartes matplotlib rtree
apt-get update apt-get install -y gcc
3.7
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==24.2.0
certifi @ file:///croot/certifi_1671487769961/work/certifi
click==8.1.8
click-plugins==1.1.1
cligj==0.7.2
cycler==0.11.0
descartes==1.1.0
exceptiongroup==1.2.2
fiona==1.9.6
fonttools==4.38.0
-e git+https://github.com/geopandas/geopandas.git@caefd7562a5cfd80cc86b37796a22f4bfa3aa9d2#egg=geopandas
importlib-metadata==6.7.0
iniconfig==2.0.0
kiwisolver==1.4.5
matplotlib==3.5.3
numpy==1.21.6
packaging==24.0
pandas==1.3.5
Pillow==9.5.0
pluggy==1.2.0
pyparsing==3.1.4
pyproj==3.2.1
pytest==7.4.4
python-dateutil==2.9.0.post0
pytz==2025.2
Rtree==1.0.1
shapely==2.0.7
six==1.17.0
tomli==2.0.1
typing_extensions==4.7.1
zipp==3.15.0

name: geopandas
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=22.3.1=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==24.2.0
      - click==8.1.8
      - click-plugins==1.1.1
      - cligj==0.7.2
      - cycler==0.11.0
      - descartes==1.1.0
      - exceptiongroup==1.2.2
      - fiona==1.9.6
      - fonttools==4.38.0
      - importlib-metadata==6.7.0
      - iniconfig==2.0.0
      - kiwisolver==1.4.5
      - matplotlib==3.5.3
      - numpy==1.21.6
      - packaging==24.0
      - pandas==1.3.5
      - pillow==9.5.0
      - pluggy==1.2.0
      - pyparsing==3.1.4
      - pyproj==3.2.1
      - pytest==7.4.4
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - rtree==1.0.1
      - shapely==2.0.7
      - six==1.17.0
      - tomli==2.0.1
      - typing-extensions==4.7.1
      - zipp==3.15.0
prefix: /opt/conda/envs/geopandas

geopandas/tests/test_plotting.py::TestPointPlotting::test_categories
geopandas/tests/test_plotting.py::TestPointPlotting::test_markerstyle geopandas/tests/test_plotting.py::TestPointPlotting::test_style_kwargs_alpha geopandas/tests/test_plotting.py::TestPointPlotting::test_legend geopandas/tests/test_plotting.py::TestPointPlotting::test_multipoints geopandas/tests/test_plotting.py::TestPointPlotting::test_multipoints_alpha geopandas/tests/test_plotting.py::TestLineStringPlotting::test_single_color geopandas/tests/test_plotting.py::TestLineStringPlotting::test_style_kwargs_linestyle geopandas/tests/test_plotting.py::TestLineStringPlotting::test_style_kwargs_linewidth geopandas/tests/test_plotting.py::TestLineStringPlotting::test_style_kwargs_alpha geopandas/tests/test_plotting.py::TestLineStringPlotting::test_subplots_norm geopandas/tests/test_plotting.py::TestLineStringPlotting::test_multilinestrings geopandas/tests/test_plotting.py::TestPolygonPlotting::test_single_color geopandas/tests/test_plotting.py::TestPolygonPlotting::test_vmin_vmax geopandas/tests/test_plotting.py::TestPolygonPlotting::test_style_kwargs_color geopandas/tests/test_plotting.py::TestPolygonPlotting::test_style_kwargs_linestyle geopandas/tests/test_plotting.py::TestPolygonPlotting::test_style_kwargs_linewidth geopandas/tests/test_plotting.py::TestPolygonPlotting::test_legend_kwargs geopandas/tests/test_plotting.py::TestPolygonPlotting::test_colorbar_kwargs geopandas/tests/test_plotting.py::TestPolygonPlotting::test_multipolygons_color geopandas/tests/test_plotting.py::TestPolygonPlotting::test_multipolygons_linestyle geopandas/tests/test_plotting.py::TestPolygonPlotting::test_multipolygons_linewidth geopandas/tests/test_plotting.py::TestPolygonPlotting::test_multipolygons_alpha geopandas/tests/test_plotting.py::TestPolygonPlotting::test_subplots_norm geopandas/tests/test_plotting.py::TestPolygonZPlotting::test_plot geopandas/tests/test_plotting.py::TestGeometryCollectionPlotting::test_colors geopandas/tests/test_plotting.py::TestGeometryCollectionPlotting::test_values geopandas/tests/test_plotting.py::TestNonuniformGeometryPlotting::test_colors geopandas/tests/test_plotting.py::TestNonuniformGeometryPlotting::test_style_kwargs geopandas/tests/test_plotting.py::TestNonuniformGeometryPlotting::test_style_kwargs_linestyle geopandas/tests/test_plotting.py::TestNonuniformGeometryPlotting::test_style_kwargs_linewidth geopandas/tests/test_plotting.py::TestNonuniformGeometryPlotting::test_style_kwargs_alpha geopandas/tests/test_plotting.py::TestGeographicAspect::test_auto geopandas/tests/test_plotting.py::TestGeographicAspect::test_manual geopandas/tests/test_plotting.py::TestPlotCollections::test_linestrings geopandas/tests/test_plotting.py::TestPlotCollections::test_linestrings_values geopandas/tests/test_plotting.py::TestPlotCollections::test_polygons geopandas/tests/test_plotting.py::TestPlotCollections::test_polygons_values geopandas/tests/test_plotting.py::test_column_values
geopandas/tests/test_plotting.py::TestPointPlotting::test_figsize geopandas/tests/test_plotting.py::TestPointPlotting::test_default_colors geopandas/tests/test_plotting.py::TestPointPlotting::test_colormap geopandas/tests/test_plotting.py::TestPointPlotting::test_single_color geopandas/tests/test_plotting.py::TestPointPlotting::test_markersize geopandas/tests/test_plotting.py::TestPointPlotting::test_style_kwargs geopandas/tests/test_plotting.py::TestPointPlotting::test_subplots_norm geopandas/tests/test_plotting.py::TestPointPlotting::test_empty_plot geopandas/tests/test_plotting.py::TestPointPlotting::test_misssing geopandas/tests/test_plotting.py::TestPointZPlotting::test_plot geopandas/tests/test_plotting.py::TestPlotCollections::test_points geopandas/tests/test_plotting.py::TestPlotCollections::test_points_values
geopandas/plotting.py
geopandas/plotting.py