Merge branch 'master' into feature/coordinate_index

Conflicts:
	tests/test_geoseries.py
This commit is contained in:
Kelsey Jordahl
2014-07-13 15:54:11 -07:00
13 changed files with 99 additions and 29 deletions
+1 -1
View File
@@ -17,7 +17,7 @@ In particular, when submitting a pull request:
- All existing tests should pass. Please make sure that the test
suite passes, both locally and on
[Travis CI](https://travis-ci.org/kjordahl/geopandas). Status on
[Travis CI](https://travis-ci.org/geopandas/geopandas). Status on
Travis will be visible on a pull request. If you want to enable
Travis CI on your own fork, please read the pandas guidelines link
above or the
+1 -1
View File
@@ -1,4 +1,4 @@
GeoPandas [![build status](https://secure.travis-ci.org/kjordahl/geopandas.png?branch=master)](https://travis-ci.org/kjordahl/geopandas) [![Coverage Status](https://coveralls.io/repos/kjordahl/geopandas/badge.png)](https://coveralls.io/r/kjordahl/geopandas)
GeoPandas [![build status](https://secure.travis-ci.org/geopandas/geopandas.png?branch=master)](https://travis-ci.org/geopandas/geopandas) [![Coverage Status](https://coveralls.io/repos/geopandas/geopandas/badge.png)](https://coveralls.io/r/geopandas/geopandas)
=========
Python tools for geographic data
+2 -2
View File
@@ -41,7 +41,7 @@ master_doc = 'index'
# General information about the project.
project = u'GeoPandas'
copyright = u'2013, GeoPandas developers'
copyright = u'2013-2014, GeoPandas developers'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@@ -52,7 +52,7 @@ try:
version = release = d['version']
except:
# FIXME: This shouldn't be hardwired, but should be set one place only
version = release = '0.1.0.dev'
version = release = '0.2.0.dev'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
+17 -8
View File
@@ -1,14 +1,23 @@
Installation
============
GeoPandas is continuous-release software. You may install the latest
source from `GitHub`_ and use the setup script::
The released version of GeoPandas is 0.1. To install the released
version, use ``pip install geopandas``.
You may install the latest development version by cloning the
`GitHub`_ repository and using the setup script::
git clone https://github.com/geopandas/geopandas.git
cd geopandas
python setup.py install
GeoPandas is also available on `PyPI`_, so ``pip install geopandas``
should work as well. You will have to add the ``--pre`` flag
for pip 1.4 and later.
It is also possible to install the latest development version
available on PyPI with `pip` by adding the ``--pre`` flag for pip 1.4
and later, or to use `pip` to install directly from the GitHub
repository with::
pip install git+git://github.com/geopandas/geopandas.git
Dependencies
------------
@@ -20,7 +29,7 @@ Supports Python versions 2.6, 2.7, and 3.2+.
- `shapely`_
- `fiona`_
- `six`_
- `geopy`_ 0.96.3 (optional; for geocoding)
- `geopy`_ 0.99 (optional; for geocoding)
- `psycopg2`_ (optional; for PostGIS connection)
For plotting, these additional packages may be used:
@@ -42,7 +51,7 @@ Tests are automatically run on all commits on the GitHub repository,
including pull requests, on `Travis CI`_.
.. _PyPI: https://pypi.python.org/pypi/geopandas
.. _GitHub: https://github.com/kjordahl/geopandas
.. _GitHub: https://github.com/geopandas/geopandas
.. _numpy: http://www.numpy.org
.. _pandas: http://pandas.pydata.org
.. _shapely: http://toblerity.github.io/shapely
@@ -53,7 +62,7 @@ including pull requests, on `Travis CI`_.
.. _six: https://pythonhosted.org/six
.. _psycopg2: https://pypi.python.org/pypi/psycopg2
.. _pysal: http://pysal.org
.. _Travis CI: https://travis-ci.org/kjordahl/geopandas
.. _Travis CI: https://travis-ci.org/geopandas/geopandas
.. toctree::
:maxdepth: 2
+12
View File
@@ -254,6 +254,12 @@ Additionally, the following methods are implemented:
See ``GeoSeries.bounds`` for the bounds of the geometries contained
in the series.
.. attribute:: GeoSeries.__geo_interface__
Implements the `geo_interface`_. Returns a python data structure
to represent the ``GeoSeries`` as a GeoJSON-like ``FeatureCollection``.
Note that the features will have an empty ``properties`` dict as they don't
have associated attributes (geometry only).
Methods of pandas ``Series`` objects are also available, although not
all are applicable to geometric objects and some may return a
@@ -312,6 +318,11 @@ Currently, the following methods are implemented for a ``GeoDataFrame``:
that column, otherwise calls ``GeoSeries.plot()`` on the
``geometry`` column. Wraps the ``plot_dataframe()`` function.
.. attribute:: GeoDataFrame.__geo_interface__
Implements the `geo_interface`_. Returns a python data structure
to represent the ``GeoDataFrame`` as a GeoJSON-like ``FeatureCollection``.
All pandas ``DataFrame`` methods are also available, although they may
not operate in a meaningful way on the ``geometry`` column and may not
return a ``GeoDataFrame`` result even when it would be appropriate to
@@ -480,6 +491,7 @@ borough that are in the holes:
.. _matplotlib: http://matplotlib.org
.. _fiona: http://toblerity.github.io/fiona
.. _geopy: https://github.com/geopy/geopy
.. _geo_interface: https://gist.github.com/sgillies/2217756
.. _file containing the boroughs of New York City: http://www.nyc.gov/html/dcp/download/bytes/nybb_14aav.zip
.. toctree::
+1 -1
View File
@@ -1,7 +1,7 @@
try:
from geopandas.version import version as __version__
except ImportError:
__version__ = '0.1.0.dev-unknown'
__version__ = '0.2.0.dev-unknown'
from geopandas.geoseries import GeoSeries
from geopandas.geodataframe import GeoDataFrame
+30 -5
View File
@@ -202,7 +202,7 @@ class GeoDataFrame(GeoPandasBase, DataFrame):
def to_json(self, na='null', **kwargs):
"""Returns a GeoJSON representation of the GeoDataFrame.
"""Returns a GeoJSON string representation of the GeoDataFrame.
Parameters
----------
@@ -216,6 +216,33 @@ class GeoDataFrame(GeoPandasBase, DataFrame):
The remaining *kwargs* are passed to json.dumps().
"""
return json.dumps(self._to_geo(na), **kwargs)
@property
def __geo_interface__(self):
"""Returns a python feature collection (i.e. the geointerface)
representation of the GeoDataFrame.
This differs from `_to_geo()` only in that it is a property
with a default `na` arg instead of a method
"""
return self._to_geo(na='null')
def _to_geo(self, na='null'):
"""Returns a python feature collection (i.e. the geointerface)
representation of the GeoDataFrame.
Parameters
----------
na : {'null', 'drop', 'keep'}, default 'null'
Indicates how to output missing (NaN) values in the GeoDataFrame
* null: ouput the missing entries as JSON null
* drop: remove the property from the feature. This applies to
each feature individually so that features may have
different properties
* keep: output the missing entries as NaN
"""
def fill_none(row):
"""
Takes in a Series, converts to a dictionary with null values
@@ -246,10 +273,8 @@ class GeoDataFrame(GeoPandasBase, DataFrame):
dict((k, v) for k, v in iteritems(row) if k != self._geometry_column_name),
'geometry': mapping(row[self._geometry_column_name]) }
return json.dumps(
{'type': 'FeatureCollection',
'features': [feature(i, row) for i, row in self.iterrows()]},
**kwargs )
return {'type': 'FeatureCollection',
'features': [feature(i, row) for i, row in self.iterrows()]}
def to_file(self, filename, driver="ESRI Shapefile", **kwargs):
"""
+7
View File
@@ -106,6 +106,13 @@ class GeoSeries(GeoPandasBase, Series):
g.crs = crs
return g
@property
def __geo_interface__(self):
"""Returns a GeoSeries as a python feature collection
"""
from geopandas import GeoDataFrame
return GeoDataFrame({'geometry': self}).__geo_interface__
def to_file(self, filename, driver="ESRI Shapefile", **kwargs):
from geopandas import GeoDataFrame
data = GeoDataFrame({"geometry": self,
+4 -3
View File
@@ -3,9 +3,9 @@ import binascii
from pandas import read_sql
import shapely.wkb
from geopandas import GeoSeries, GeoDataFrame
def read_postgis(sql, con, geom_col='geom', crs=None, index_col=None,
coerce_float=True, params=None):
"""
@@ -19,7 +19,7 @@ def read_postgis(sql, con, geom_col='geom', crs=None, index_col=None,
Parameters
----------
sql: string
con: DB connection object
con: DB connection object or SQLAlchemy engine
geom_col: string, default 'geom'
column name to convert to shapely geometries
crs: optional
@@ -30,8 +30,9 @@ def read_postgis(sql, con, geom_col='geom', crs=None, index_col=None,
index_col, coerce_float, params
"""
df = read_sql(sql, con, index_col=index_col, coerce_float=coerce_float,
df = read_sql(sql, con, index_col=index_col, coerce_float=coerce_float,
params=params)
if geom_col not in df:
raise ValueError("Query missing geometry column '{0}'".format(
geom_col))
+1
View File
@@ -1,4 +1,5 @@
psycopg2>=2.5.1
SQLAlchemy>=0.8.3
geopy==0.99
matplotlib>=1.2.1
descartes>=1.0
+12 -4
View File
@@ -367,8 +367,6 @@ class TestDataFrame(unittest.TestCase):
{'a': 2, 'b': np.nan}])
assert_frame_equal(expected, result)
@unittest.skipIf(PANDAS_NEW_SQL_API, 'Development version of pandas '
'not yet supported in SQL API.')
def test_from_postgis_default(self):
con = connect('test_geopandas')
if con is None or not create_db(self.df):
@@ -378,12 +376,13 @@ class TestDataFrame(unittest.TestCase):
sql = "SELECT * FROM nybb;"
df = GeoDataFrame.from_postgis(sql, con)
finally:
if PANDAS_NEW_SQL_API:
# It's not really a connection, it's an engine
con = con.connect()
con.close()
validate_boro_df(self, df)
@unittest.skipIf(PANDAS_NEW_SQL_API, 'Development version of pandas '
'not yet supported in SQL API.')
def test_from_postgis_custom_geom_col(self):
con = connect('test_geopandas')
if con is None or not create_db(self.df):
@@ -396,6 +395,9 @@ class TestDataFrame(unittest.TestCase):
FROM nybb;"""
df = GeoDataFrame.from_postgis(sql, con, geom_col='__geometry__')
finally:
if PANDAS_NEW_SQL_API:
# It's not really a connection, it's an engine
con = con.connect()
con.close()
validate_boro_df(self, df)
@@ -425,3 +427,9 @@ class TestDataFrame(unittest.TestCase):
with self.assertRaises(ValueError):
df.set_geometry('location', inplace=True)
def test_geodataframe_geointerface(self):
self.assertEqual(self.df.__geo_interface__['type'], 'FeatureCollection')
self.assertEqual(len(self.df.__geo_interface__['features']),
self.df.shape[0])
+5
View File
@@ -146,5 +146,10 @@ class TestSeries(unittest.TestCase):
self.assertTrue(geom_equals(self.g3[[True, False]], self.g3.cx[0.9:, :0.1]))
self.assertTrue(geom_equals(self.g3[[False, True]], self.g3.cx[0:0.1, 0.9:1.0]))
def test_geoseries_geointerface(self):
self.assertEqual(self.g1.__geo_interface__['type'], 'FeatureCollection')
self.assertEqual(len(self.g1.__geo_interface__['features']),
self.g1.shape[0])
if __name__ == '__main__':
unittest.main()
+6 -4
View File
@@ -16,8 +16,6 @@ class TestIO(unittest.TestCase):
with fiona.open(path, vfs=vfs) as f:
self.crs = f.crs
@unittest.skipIf(PANDAS_NEW_SQL_API, 'Development version of pandas '
'not yet supported in SQL API.')
def test_read_postgis_default(self):
con = tests.util.connect('test_geopandas')
if con is None or not tests.util.create_db(self.df):
@@ -27,12 +25,13 @@ class TestIO(unittest.TestCase):
sql = "SELECT * FROM nybb;"
df = read_postgis(sql, con)
finally:
if PANDAS_NEW_SQL_API:
# It's not really a connection, it's an engine
con = con.connect()
con.close()
tests.util.validate_boro_df(self, df)
@unittest.skipIf(PANDAS_NEW_SQL_API, 'Development version of pandas '
'not yet supported in SQL API.')
def test_read_postgis_custom_geom_col(self):
con = tests.util.connect('test_geopandas')
if con is None or not tests.util.create_db(self.df):
@@ -45,6 +44,9 @@ class TestIO(unittest.TestCase):
FROM nybb;"""
df = read_postgis(sql, con, geom_col='__geometry__')
finally:
if PANDAS_NEW_SQL_API:
# It's not really a connection, it's an engine
con = con.connect()
con.close()
tests.util.validate_boro_df(self, df)