mirror of
https://github.com/wassname/geopandas.git
synced 2026-10-03 12:31:14 +08:00
Use mapclassify instead of PySAL due to change of PySAL structure. (#872)
This commit is contained in:
1 parent
bf7ba2f6a2
commit
f4fa69eae0
13 files changed
+56
-46
No files matched your search
@@ -19,7 +19,6 @@ dependencies:
|
||||
- rtree
|
||||
- matplotlib
|
||||
- descartes
|
||||
- pysal
|
||||
#- geopy
|
||||
- SQLalchemy
|
||||
- psycopg2
|
||||
@@ -28,3 +27,4 @@ dependencies:
|
||||
- git+https://github.com/pydata/pandas.git
|
||||
- codecov
|
||||
- geopy
|
||||
- mapclassify==1.0.1
|
||||
@@ -18,7 +18,7 @@ dependencies:
|
||||
- rtree
|
||||
- matplotlib
|
||||
- descartes
|
||||
- pysal
|
||||
- mapclassify==1.0.1
|
||||
#- geopy
|
||||
- SQLalchemy
|
||||
- psycopg2
|
||||
|
||||
@@ -18,7 +18,6 @@ dependencies:
|
||||
- rtree
|
||||
- matplotlib
|
||||
- descartes
|
||||
- pysal
|
||||
#- geopy
|
||||
- SQLalchemy
|
||||
- psycopg2
|
||||
@@ -26,3 +25,4 @@ dependencies:
|
||||
- pip:
|
||||
- codecov
|
||||
- geopy
|
||||
- mapclassify==1.0.1
|
||||
@@ -20,8 +20,8 @@ dependencies:
|
||||
- rtree
|
||||
- matplotlib==2.0.2
|
||||
- descartes
|
||||
- pysal
|
||||
- geopy
|
||||
- SQLalchemy
|
||||
- psycopg2
|
||||
- libspatialite
|
||||
- mapclassify==1.0.1
|
||||
@@ -18,7 +18,7 @@ dependencies:
|
||||
- rtree
|
||||
- matplotlib==1.5.3
|
||||
- descartes
|
||||
- pysal
|
||||
- mapclassify
|
||||
- geopy
|
||||
- SQLalchemy
|
||||
- psycopg2
|
||||
|
||||
@@ -17,7 +17,7 @@ dependencies:
|
||||
- rtree
|
||||
- matplotlib==1.5.3
|
||||
- descartes
|
||||
- pysal
|
||||
- mapclassify
|
||||
- geopy
|
||||
- SQLalchemy
|
||||
- psycopg2
|
||||
|
||||
@@ -17,7 +17,6 @@ dependencies:
|
||||
- rtree
|
||||
- matplotlib==2.0.2
|
||||
- descartes
|
||||
- pysal
|
||||
#- geopy
|
||||
- SQLalchemy
|
||||
- psycopg2
|
||||
@@ -25,3 +24,4 @@ dependencies:
|
||||
- pip:
|
||||
- codecov
|
||||
- geopy
|
||||
- mapclassify
|
||||
@@ -18,7 +18,6 @@ dependencies:
|
||||
- rtree
|
||||
- matplotlib
|
||||
- descartes
|
||||
- pysal
|
||||
#- geopy
|
||||
- SQLalchemy
|
||||
- psycopg2
|
||||
@@ -28,3 +27,4 @@ dependencies:
|
||||
- git+https://github.com/pydata/pandas.git
|
||||
- codecov
|
||||
- geopy
|
||||
- mapclassify
|
||||
@@ -17,7 +17,7 @@ dependencies:
|
||||
- rtree
|
||||
- matplotlib
|
||||
- descartes
|
||||
- pysal
|
||||
- mapclassify
|
||||
- geopy
|
||||
- SQLalchemy
|
||||
- psycopg2
|
||||
|
||||
@@ -17,7 +17,6 @@ dependencies:
|
||||
- rtree
|
||||
- matplotlib
|
||||
- descartes
|
||||
- pysal
|
||||
#- geopy
|
||||
- SQLalchemy
|
||||
- psycopg2
|
||||
@@ -25,3 +24,4 @@ dependencies:
|
||||
- pip:
|
||||
- codecov
|
||||
- geopy
|
||||
- mapclassify
|
||||
+35
-23
@@ -26,7 +26,7 @@ def _flatten_multi_geoms(geoms, colors=None):
|
||||
colors = [None] * len(geoms)
|
||||
|
||||
components, component_colors = [], []
|
||||
|
||||
|
||||
if not geoms.geom_type.str.startswith('Multi').any():
|
||||
return geoms, colors
|
||||
|
||||
@@ -349,10 +349,10 @@ def plot_dataframe(df, column=None, cmap=None, color=None, ax=None,
|
||||
legend : bool (default False)
|
||||
Plot a legend. Ignored if no `column` is given, or if `color` is given.
|
||||
scheme : str (default None)
|
||||
Name of a choropleth classification scheme (requires PySAL).
|
||||
A pysal.esda.mapclassify.Map_Classifier object will be used
|
||||
under the hood. Supported schemes: 'Equal_interval', 'Quantiles',
|
||||
'Fisher_Jenks'
|
||||
Name of a choropleth classification scheme (requires mapclassify).
|
||||
A mapclassify.Map_Classifier object will be used
|
||||
under the hood. Supported schemes: 'Quantiles',
|
||||
'Equal_Interval', 'Fisher_Jenks', 'Fisher_Jenks_Sampled'
|
||||
k : int (default 5)
|
||||
Number of classes (ignored if scheme is None)
|
||||
vmin : None or float (default None)
|
||||
@@ -445,7 +445,7 @@ def plot_dataframe(df, column=None, cmap=None, color=None, ax=None,
|
||||
values = np.array([valuemap[k] for k in values])
|
||||
|
||||
if scheme is not None:
|
||||
binning = __pysal_choro(values, scheme, k=k)
|
||||
binning = _mapclassify_choro(values, scheme, k=k)
|
||||
# set categorical to True for creating the legend
|
||||
categorical = True
|
||||
binedges = [values.min()] + binning.bins.tolist()
|
||||
@@ -513,17 +513,18 @@ def plot_dataframe(df, column=None, cmap=None, color=None, ax=None,
|
||||
return ax
|
||||
|
||||
|
||||
def __pysal_choro(values, scheme, k=5):
|
||||
def _mapclassify_choro(values, scheme, k=5):
|
||||
"""
|
||||
Wrapper for choropleth schemes from PySAL for use with plot_dataframe
|
||||
Wrapper for choropleth schemes from mapclassify for use with plot_dataframe
|
||||
|
||||
Parameters
|
||||
----------
|
||||
values
|
||||
Series to be plotted
|
||||
scheme : str
|
||||
One of pysal.esda.mapclassify classification schemes
|
||||
Options are 'Equal_interval', 'Quantiles', 'Fisher_Jenks'
|
||||
One of mapclassify classification schemes
|
||||
Options are 'Quantiles', 'Equal_Interval', 'Fisher_Jenks',
|
||||
'Fisher_Jenks_Sampled'
|
||||
k : int
|
||||
number of classes (2 <= k <=9)
|
||||
|
||||
@@ -535,17 +536,28 @@ def __pysal_choro(values, scheme, k=5):
|
||||
|
||||
"""
|
||||
try:
|
||||
from pysal.esda.mapclassify import (
|
||||
Quantiles, Equal_Interval, Fisher_Jenks)
|
||||
schemes = {}
|
||||
schemes['equal_interval'] = Equal_Interval
|
||||
schemes['quantiles'] = Quantiles
|
||||
schemes['fisher_jenks'] = Fisher_Jenks
|
||||
scheme = scheme.lower()
|
||||
if scheme not in schemes:
|
||||
raise ValueError("Invalid scheme. Scheme must be in the"
|
||||
" set: %r" % schemes.keys())
|
||||
binning = schemes[scheme](values, k)
|
||||
return binning
|
||||
from mapclassify import (
|
||||
Quantiles, Equal_Interval, Fisher_Jenks,
|
||||
Fisher_Jenks_Sampled)
|
||||
except ImportError:
|
||||
raise ImportError("PySAL is required to use the 'scheme' keyword")
|
||||
try:
|
||||
from mapclassify.api import (
|
||||
Quantiles, Equal_Interval, Fisher_Jenks,
|
||||
Fisher_Jenks_Sampled)
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
"The 'mapclassify' package is required to use the 'scheme' "
|
||||
"keyword")
|
||||
|
||||
schemes = {}
|
||||
schemes['equal_interval'] = Equal_Interval
|
||||
schemes['quantiles'] = Quantiles
|
||||
schemes['fisher_jenks'] = Fisher_Jenks
|
||||
schemes['fisher_jenks_sampled'] = Fisher_Jenks_Sampled
|
||||
|
||||
scheme = scheme.lower()
|
||||
if scheme not in schemes:
|
||||
raise ValueError("Invalid scheme. Scheme must be in the"
|
||||
" set: %r" % schemes.keys())
|
||||
binning = schemes[scheme](values, k)
|
||||
return binning
|
||||
@@ -12,6 +12,7 @@ from shapely.affinity import rotate
|
||||
from shapely.geometry import MultiPolygon, Polygon, LineString, Point, MultiPoint
|
||||
|
||||
from geopandas import GeoSeries, GeoDataFrame, read_file
|
||||
from geopandas.datasets import get_path
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -386,39 +387,36 @@ class TestNonuniformGeometryPlotting:
|
||||
assert ax.collections[2].get_sizes() == [10]
|
||||
|
||||
|
||||
class TestPySALPlotting:
|
||||
class TestMapclassifyPlotting:
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
try:
|
||||
import pysal as ps
|
||||
except ImportError:
|
||||
raise pytest.skip("PySAL is not installed")
|
||||
|
||||
pth = ps.examples.get_path("columbus.shp")
|
||||
pytest.importorskip('mapclassify')
|
||||
pth = get_path('naturalearth_lowres')
|
||||
cls.df = read_file(pth)
|
||||
cls.df['NEGATIVES'] = np.linspace(-10, 10, len(cls.df.index))
|
||||
|
||||
def test_legend(self):
|
||||
with warnings.catch_warnings(record=True) as _: # don't print warning
|
||||
# warning coming from pysal / scipy.stats
|
||||
ax = self.df.plot(column='CRIME', scheme='QUANTILES', k=3,
|
||||
# warning coming from scipy.stats
|
||||
ax = self.df.plot(column='pop_est', scheme='QUANTILES', k=3,
|
||||
cmap='OrRd', legend=True)
|
||||
labels = [t.get_text() for t in ax.get_legend().get_texts()]
|
||||
expected = [u'0.18 - 26.07', u'26.07 - 41.97', u'41.97 - 68.89']
|
||||
expected = [u'-99.00 - 4579438.67', u'4579438.67 - 16639804.33',
|
||||
u'16639804.33 - 1338612970.00']
|
||||
assert labels == expected
|
||||
|
||||
def test_negative_legend(self):
|
||||
ax = self.df.plot(column='NEGATIVES', scheme='FISHER_JENKS', k=3,
|
||||
cmap='OrRd', legend=True)
|
||||
labels = [t.get_text() for t in ax.get_legend().get_texts()]
|
||||
expected = [u'-10.00 - -3.33', u'-3.33 - 3.33', u'3.33 - 10.00']
|
||||
expected = [u'-10.00 - -3.41', u'-3.41 - 3.30', u'3.30 - 10.00']
|
||||
assert labels == expected
|
||||
|
||||
def test_invalid_scheme(self):
|
||||
with pytest.raises(ValueError):
|
||||
scheme = 'invalid_scheme_*#&)(*#'
|
||||
self.df.plot(column='CRIME', scheme=scheme, k=3,
|
||||
self.df.plot(column='gdp_md_est', scheme=scheme, k=3,
|
||||
cmap='OrRd', legend=True)
|
||||
|
||||
|
||||
|
||||
@@ -8,4 +8,4 @@ pytest>=3.1.0
|
||||
pytest-cov
|
||||
codecov
|
||||
rtree>=0.8
|
||||
pysal
|
||||
mapclassify
|
||||
Reference in new issue
Block a user