Merge branch 'master' into 259-plotting-collections

This commit is contained in:
Jeffrey Gerard
2016-04-30 20:24:31 +02:00
53 changed files with 1446 additions and 297 deletions
+2
View File
@@ -6,3 +6,5 @@ doc/_build
geopandas.egg-info
geopandas/version.py
*.py~
doc/_static/world_*
examples/nybb_*.zip
+1 -1
View File
@@ -78,7 +78,7 @@ install:
- if [[ $PANDAS == 'master' ]]; then pip install git+https://github.com/pydata/pandas.git; else pip wheel pandas==$PANDAS; pip install pandas==$PANDAS; fi
script:
- py.test tests --cov geopandas -v --cov-report term-missing
- py.test geopandas --cov geopandas -v --cov-report term-missing
after_success:
- coveralls
+1 -1
View File
@@ -80,7 +80,7 @@ GeoPandas objects also know how to plot themselves. GeoPandas uses [descartes](
>>> g.plot()
GeoPandas also implements alternate constructors that can read any data format recognized by [fiona](http://toblerity.github.io/fiona). To read a [file containing the boroughs of New York City](http://www.nyc.gov/html/dcp/download/bytes/nybb_14aav.zip):
GeoPandas also implements alternate constructors that can read any data format recognized by [fiona](http://toblerity.github.io/fiona). To read a [file containing the boroughs of New York City](http://www1.nyc.gov/assets/planning/download/zip/data-maps/open-data/nybb_16a.zip):
>>> boros = GeoDataFrame.from_file('nybb.shp')
>>> boros.set_index('BoroCode', inplace=True)
+16
View File
@@ -0,0 +1,16 @@
name: geopandas_docs
channels:
- conda-forge
dependencies:
- python=3.4
- pandas
- shapely
- fiona
- pyproj
- six
- geopy
- matplotlib
- descartes
- sphinx
- sphinx_rtd_theme
- ipython=4.0.1
@@ -0,0 +1,336 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en-US">
<head profile="http://gmpg.org/xfn/11">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Populated Places | Natural Earth</title>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
<link rel="alternate" type="application/rss+xml" title="Natural Earth RSS Feed" href="http://www.naturalearthdata.com/feed/" />
<link rel="pingback" href="http://www.naturalearthdata.com/xmlrpc.php" />
<script type="text/javascript" src="http://www.naturalearthdata.com/wp-content/themes/NEV/includes/js/suckerfish.js"></script>
<!--[if lt IE 7]>
<script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE7.js" type="text/javascript"></script>
<script defer="defer" type="text/javascript" src="http://www.naturalearthdata.com/wp-content/themes/NEV/includes/js/pngfix.js"></script>
<![endif]-->
<link rel="stylesheet" href="http://www.naturalearthdata.com/wp-content/themes/NEV/style.css" type="text/css" media="screen" />
<meta name='Admin Management Xtended WordPress plugin' content='2.1.1' />
<link rel="alternate" type="application/rss+xml" title="Natural Earth &raquo; Populated Places Comments Feed" href="http://www.naturalearthdata.com/downloads/10m-cultural-vectors/10m-populated-places/feed/" />
<link rel='stylesheet' id='sociable-front-css-css' href='http://www.naturalearthdata.com/wp-content/plugins/sociable/sociable.css?ver=2.9.2' type='text/css' media='' />
<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://www.naturalearthdata.com/xmlrpc.php?rsd" />
<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://www.naturalearthdata.com/wp-includes/wlwmanifest.xml" />
<link rel='index' title='Natural Earth' href='http://www.naturalearthdata.com' />
<link rel='start' title='Welcome to the Natural Earth Blog' href='http://www.naturalearthdata.com/blog/miscellaneous/test/' />
<link rel='prev' title='Antarctic Ice Shelves' href='http://www.naturalearthdata.com/downloads/10m-physical-vectors/10m-antarctic-ice-shelves/' />
<link rel='next' title='Admin 1 &#8211; States, Provinces' href='http://www.naturalearthdata.com/downloads/10m-cultural-vectors/10m-admin-1-states-provinces/' />
<meta name="generator" content="WordPress 2.9.2" />
<!-- All in One SEO Pack 1.6.10.2 by Michael Torbert of Semper Fi Web Design[309,448] -->
<meta name="description" content="City and town points, from Tokyo to Wasilla, Cairo to Kandahar About Point symbols with name attributes. Includes all admin-0 and many" />
<link rel="canonical" href="http://www.naturalearthdata.com/downloads/10m-cultural-vectors/10m-populated-places/" />
<!-- /all in one seo pack -->
<!-- begin gallery scripts -->
<link rel="stylesheet" href="http://www.naturalearthdata.com/wp-content/plugins/featured-content-gallery/css/jd.gallery.css.php" type="text/css" media="screen" charset="utf-8"/>
<link rel="stylesheet" href="http://www.naturalearthdata.com/wp-content/plugins/featured-content-gallery/css/jd.gallery.css" type="text/css" media="screen" charset="utf-8"/>
<script type="text/javascript" src="http://www.naturalearthdata.com/wp-content/plugins/featured-content-gallery/scripts/mootools.v1.11.js"></script>
<script type="text/javascript" src="http://www.naturalearthdata.com/wp-content/plugins/featured-content-gallery/scripts/jd.gallery.js.php"></script>
<script type="text/javascript" src="http://www.naturalearthdata.com/wp-content/plugins/featured-content-gallery/scripts/jd.gallery.transitions.js"></script>
<!-- end gallery scripts -->
<style type="text/css">.broken_link, a.broken_link {
text-decoration: line-through;
}</style><link href="http://www.naturalearthdata.com/wp-content/themes/NEV/css/default.css" rel="stylesheet" type="text/css" />
<style type="text/css">.recentcomments a{display:inline !important;padding:0 !important;margin:0 !important;}</style>
<!--[if lte IE 7]>
<link rel="stylesheet" type="text/css" href="http://www.naturalearthdata.com/wp-content/themes/NEV/ie.css" />
<![endif]-->
<script src="http://www.naturalearthdata.com/wp-content/themes/NEV/js/jquery-1.2.6.min.js" type="text/javascript" charset="utf-8"></script>
<script>
jQuery.noConflict();
</script>
<script type="text/javascript" charset="utf-8">
$(function(){
var tabContainers = $('div#maintabdiv > div');
tabContainers.hide().filter('#comments').show();
$('div#maintabdiv ul#tabnav a').click(function () {
tabContainers.hide();
tabContainers.filter(this.hash).show();
$('div#maintabdiv ul#tabnav a').removeClass('current');
$(this).addClass('current');
return false;
}).filter('#comments').click();
});
</script>
<script type="text/javascript" language="javascript" src="http://www.naturalearthdata.com/dataTables/media/js/jquery.dataTables.js"></script>
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
$('#ne_table').dataTable();
} );
</script>
</head>
<body>
<div id="page">
<div id="header">
<div id="headerimg">
<h1><a href="http://www.naturalearthdata.com/"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/nev_logo.png" alt="Natural Earth title="Natural Earth" /></a></h1>
<div class="description">Free vector and raster map data at 1:10m, 1:50m, and 1:110m scales</div>
<div class="header_search"><form method="get" id="searchform" action="http://www.naturalearthdata.com/">
<label class="hidden" for="s">Search for:</label>
<div><input type="text" value="" name="s" id="s" />
<input type="submit" id="searchsubmit" value="Search" />
</div>
</form>
</div>
<!--<div class="translate_panel" style="align:top; margin-left:650px; top:50px;">
<div id="google_translate_element" style="float:left;"></div>
<script>
function googleTranslateElementInit() {
new google.translate.TranslateElement({
pageLanguage: 'en'
}, 'google_translate_element');
}
</script>
<script src="http://translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>
</div>-->
</div>
</div>
<div id="pagemenu" style="align:bottom;">
<ul id="page-list" class="clearfix"><li class="page_item page-item-4"><a href="http://www.naturalearthdata.com" title="Home">Home</a></li>
<li class="page_item page-item-10"><a href="http://www.naturalearthdata.com/features/" title="Features">Features</a></li>
<li class="page_item page-item-12"><a href="http://www.naturalearthdata.com/downloads/" title="Downloads">Downloads</a></li>
<li class="page_item page-item-6 current_page_parent"><a href="http://www.naturalearthdata.com/blog/" title="Blog">Blog</a></li>
<li class="page_item page-item-14"><a href="http://www.naturalearthdata.com/forums" title="Forums">Forums</a></li>
<li class="page_item page-item-366"><a href="http://www.naturalearthdata.com/corrections" title="Corrections">Corrections</a></li>
<li class="page_item page-item-16"><a href="http://www.naturalearthdata.com/about/" title="About">About</a></li>
</ul>
</div>
<hr /> <div id="main">
<div id="content" class="narrowcolumn">
&laquo; <a href="http://www.naturalearthdata.com/downloads/10m-cultural-vectors/">1:10m Cultural Vectors</a>&nbsp;
<div class="post" id="post-472">
<h2>Populated Places</h2>
<div class="entry">
<div class="downloadPromoBlock" style="float: left;">
<div style="float: left; width: 170px;"><img class="alignnone size-full wp-image-1918" title="pop_thumb" src="http://www.naturalearthdata.com/wp-content/uploads/2009/09/pop_thumb.png" alt="pop_thumb" width="150" height="97" /></div>
<div style="float: left; width: 410px;"><em>City and town points, from Tokyo to Wasilla, Cairo to Kandahar</em>
<div class="download-link-div">
<a class="download-link" rel="nofollow" title="Downloaded 26754 times (Shapefile, geoDB, or TIFF format)" onclick="if (window.urchinTracker) urchinTracker ('http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_populated_places.zip');" href="http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_populated_places.zip" onclick="javascript:pageTracker._trackPageview('/downloads/http///download/10m/cultural/ne_10m_populated_places.zip');">Download populated places</a> <span class="download-link-span">(1.51 MB) version 2.0.0</span>
</div> <div class="download-link-div">
<a class="download-link" rel="nofollow" title="Downloaded 2515 times (Shapefile, geoDB, or TIFF format)" onclick="if (window.urchinTracker) urchinTracker ('http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_populated_places_simple.zip');" href="http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_populated_places_simple.zip" onclick="javascript:pageTracker._trackPageview('/downloads/http///download/10m/cultural/ne_10m_populated_places_simple.zip');">Download simple (less columns)</a> <span class="download-link-span">(719.87 KB) version 2.0.0</span>
</div>
<span id="more-472"></span></div>
</div>
<div class="downloadMainBlock" style="float: left;">
<p><strong>About</strong></p>
<p>Point symbols with name attributes. Includes all admin-0 and many admin-1 capitals, major cities and towns, plus a sampling of smaller towns in sparsely inhabited regions. We favor regional significance over population census in determining our selection of places. Use the scale rankings to filter the number of towns that appear on your map.</p>
<p><img class="alignnone size-full wp-image-1920" title="pop_banner" src="http://www.naturalearthdata.com/wp-content/uploads/2009/09/pop_banner.png" alt="pop_banner" width="580" height="150" /></p>
<p><a href="http://www.ornl.gov/sci/landscan/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.ornl.gov/sci/landscan/');">LandScan</a> derived population estimates are provided for 90% of our cities. Those lacking population estimates are often in sparsely inhabited areas. We provide a range of population values that account for the total &#8220;metropolitan&#8221; population rather than it&#8217;s administrative boundary population. Use the PopMax column to size your town labels. Starting in version 1.1, popMax has been throttled down to the UN estimated metro population for the ~500 largest urban areas in the world. This affects towns in China, India, and parts of Africa where our Landscan counting method usually over estimated.</p>
<p>Population estimates were derived from the LANDSCAN dataset maintained and distributed by the Oak Ridge National Laboratory. These data were converted from raster to vector and pixels with fewer than 200 persons per square kilometer were removed from the dataset as they were classified as rural. Once urban pixels were selected, these pixels were aggregated into contiguous units. Concurrently Thiessen polygons were created based on the selected city points. The Thiessen polygons were used to intersect the contiguous city boundaries to produce bounded areas for the cities. As a result, our estimates capture a metropolitan and micropolitan populations per city regardless of administrative units.</p>
<p>Once intersected, the contiguous polygons were recalculated, using aerial interpolation assuming uniform population distribution within each pixel, to determine the population total. This process was conducted multiple times, for each scale level, to produce population estimates for each city at nested scales of 1:300 million, 1:110 million, 1:50 million, 1:20 million, and 1:10 million. </p>
<div class="download-link-div">
<a class="download-link" rel="nofollow" title="Downloaded 481 times (Shapefile, geoDB, or TIFF format)" onclick="if (window.urchinTracker) urchinTracker ('http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_urban_areas_landscan.zip');" href="http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_urban_areas_landscan.zip" onclick="javascript:pageTracker._trackPageview('/downloads/http///download/10m/cultural/ne_10m_urban_areas_landscan.zip');">Download landscan urban areas</a> <span class="download-link-span">(13.01 MB) version 2.0.0</span>
</div>
<p><strong>Population ranks</strong></p>
<p>Are calculated as rank_max and rank_min using this general VB formula that can be pasted into ArcMap Field Calculator advanced area (set your output to x):</p>
<blockquote><p>
a = [pop_max]</p>
<p>if( a > 10000000 ) then
x = 14
elseif( a > 5000000 ) then
x = 13
elseif( a > 1000000 ) then
x = 12
elseif( a > 500000 ) then
x = 11
elseif( a > 200000 ) then
x = 10
elseif( a > 100000 ) then
x = 9
elseif( a > 50000 ) then
x = 8
elseif( a > 20000 ) then
x = 7
elseif( a > 10000 ) then
x = 6
elseif( a > 5000 ) then
x = 5
elseif( a > 2000 ) then
x = 4
elseif( a > 1000 ) then
x = 3
elseif( a > 200 ) then
x = 2
elseif( a > 0 ) then
x = 1
else
x = 0
end if</p></blockquote>
<p><strong>Issues</strong></p>
<p>While we don&#8217;t want to show every admin-1 capital, for those countries where we show most admin-1 capitals, we should have a complete set. If you find we are missing one, please log it in the Cx tool at right.</p>
<p><strong>Version History</strong></p>
<ul>
<li>
<a rel="nofollow" title="Download version 2.0.0 of ne_10m_populated_places.zip" href="http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_populated_places.zip" onclick="javascript:pageTracker._trackPageview('/downloads/http///download/10m/cultural/ne_10m_populated_places.zip');">2.0.0</a>
</li>
<li>
1.4.0
</li>
<li>
1.3.0
</li>
<li>
1.1.0
</li>
<li>
0.9.0
</li>
</ul>
<p><a href="https://github.com/nvkelso/natural-earth-vector/blob/master/CHANGELOG" onclick="javascript:pageTracker._trackPageview('/outbound/article/https://github.com/nvkelso/natural-earth-vector/blob/master/CHANGELOG');">The master changelog is available on Github »</a>
</div>
<div class="sociable">
<div class="sociable_tagline">
<strong>Share and Enjoy:</strong>
</div>
<ul>
<li class="sociablefirst"><a rel="nofollow" target="_blank" href="http://twitter.com/home?status=Populated%20Places%20-%20http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://twitter.com/home?status=Populated%20Places%20-%20http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F');" title="Twitter"><img src="http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.gif" title="Twitter" alt="Twitter" style="width: 16px; height: 16px; background: transparent url(http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.png) no-repeat; background-position:-343px -55px" class="sociable-hovers" /></a></li>
<li><a rel="nofollow" target="_blank" href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;t=Populated%20Places" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;t=Populated%20Places');" title="Facebook"><img src="http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.gif" title="Facebook" alt="Facebook" style="width: 16px; height: 16px; background: transparent url(http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.png) no-repeat; background-position:-343px -1px" class="sociable-hovers" /></a></li>
<li><a rel="nofollow" target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places&amp;bodytext=%0D%0A%0D%0ACity%20and%20town%20points%2C%20from%20Tokyo%20to%20Wasilla%2C%20Cairo%20to%20Kandahar%0D%0A%5Bdrain%20file%2039%20show%20nev_download%5D%20%5Bdrain%20file%20224%20show%20nev_download%5D%0D%0A%0D%0A%0D%0A%0D%0A%0D%0AAbout%0D%0A%0D%0APoint%20symbols%20with%20name%20attributes.%20Includes%20all%20admin-0%20and%20many%20admin-1%20capitals%2C%20major%20citie" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places&amp;bodytext=%0D%0A%0D%0ACity%20and%20town%20points%2C%20from%20Tokyo%20to%20Wasilla%2C%20Cairo%20to%20Kandahar%0D%0A%5Bdrain%20file%2039%20show%20nev_download%5D%20%5Bdrain%20file%20224%20show%20nev_download%5D%0D%0A%0D%0A%0D%0A%0D%0A%0D%0AAbout%0D%0A%0D%0APoint%20symbols%20with%20name%20attributes.%20Includes%20all%20admin-0%20and%20many%20admin-1%20capitals%2C%20major%20citie');" title="Digg"><img src="http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.gif" title="Digg" alt="Digg" style="width: 16px; height: 16px; background: transparent url(http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.png) no-repeat; background-position:-235px -1px" class="sociable-hovers" /></a></li>
<li><a rel="nofollow" target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places&amp;notes=%0D%0A%0D%0ACity%20and%20town%20points%2C%20from%20Tokyo%20to%20Wasilla%2C%20Cairo%20to%20Kandahar%0D%0A%5Bdrain%20file%2039%20show%20nev_download%5D%20%5Bdrain%20file%20224%20show%20nev_download%5D%0D%0A%0D%0A%0D%0A%0D%0A%0D%0AAbout%0D%0A%0D%0APoint%20symbols%20with%20name%20attributes.%20Includes%20all%20admin-0%20and%20many%20admin-1%20capitals%2C%20major%20citie" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://delicious.com/post?url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places&amp;notes=%0D%0A%0D%0ACity%20and%20town%20points%2C%20from%20Tokyo%20to%20Wasilla%2C%20Cairo%20to%20Kandahar%0D%0A%5Bdrain%20file%2039%20show%20nev_download%5D%20%5Bdrain%20file%20224%20show%20nev_download%5D%0D%0A%0D%0A%0D%0A%0D%0A%0D%0AAbout%0D%0A%0D%0APoint%20symbols%20with%20name%20attributes.%20Includes%20all%20admin-0%20and%20many%20admin-1%20capitals%2C%20major%20citie');" title="del.icio.us"><img src="http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.gif" title="del.icio.us" alt="del.icio.us" style="width: 16px; height: 16px; background: transparent url(http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.png) no-repeat; background-position:-199px -1px" class="sociable-hovers" /></a></li>
<li><a rel="nofollow" target="_blank" href="http://www.google.com/bookmarks/mark?op=edit&amp;bkmk=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places&amp;annotation=%0D%0A%0D%0ACity%20and%20town%20points%2C%20from%20Tokyo%20to%20Wasilla%2C%20Cairo%20to%20Kandahar%0D%0A%5Bdrain%20file%2039%20show%20nev_download%5D%20%5Bdrain%20file%20224%20show%20nev_download%5D%0D%0A%0D%0A%0D%0A%0D%0A%0D%0AAbout%0D%0A%0D%0APoint%20symbols%20with%20name%20attributes.%20Includes%20all%20admin-0%20and%20many%20admin-1%20capitals%2C%20major%20citie" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.google.com/bookmarks/mark?op=edit&amp;bkmk=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places&amp;annotation=%0D%0A%0D%0ACity%20and%20town%20points%2C%20from%20Tokyo%20to%20Wasilla%2C%20Cairo%20to%20Kandahar%0D%0A%5Bdrain%20file%2039%20show%20nev_download%5D%20%5Bdrain%20file%20224%20show%20nev_download%5D%0D%0A%0D%0A%0D%0A%0D%0A%0D%0AAbout%0D%0A%0D%0APoint%20symbols%20with%20name%20attributes.%20Includes%20all%20admin-0%20and%20many%20admin-1%20capitals%2C%20major%20citie');" title="Google Bookmarks"><img src="http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.gif" title="Google Bookmarks" alt="Google Bookmarks" style="width: 16px; height: 16px; background: transparent url(http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.png) no-repeat; background-position:-91px -19px" class="sociable-hovers" /></a></li>
<li><a rel="nofollow" target="_blank" href="http://slashdot.org/bookmark.pl?title=Populated%20Places&amp;url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://slashdot.org/bookmark.pl?title=Populated%20Places&amp;url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F');" title="Slashdot"><img src="http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.gif" title="Slashdot" alt="Slashdot" style="width: 16px; height: 16px; background: transparent url(http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.png) no-repeat; background-position:-145px -55px" class="sociable-hovers" /></a></li>
<li><a rel="nofollow" target="_blank" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places');" title="StumbleUpon"><img src="http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.gif" title="StumbleUpon" alt="StumbleUpon" style="width: 16px; height: 16px; background: transparent url(http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.png) no-repeat; background-position:-217px -55px" class="sociable-hovers" /></a></li>
<li><a rel="nofollow" target="_blank" href="mailto:?subject=Populated%20Places&amp;body=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F" title="email"><img src="http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.gif" title="email" alt="email" style="width: 16px; height: 16px; background: transparent url(http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.png) no-repeat; background-position:-325px -1px" class="sociable-hovers" /></a></li>
<li><a rel="nofollow" target="_blank" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places&amp;source=Natural+Earth+Free+vector+and+raster+map+data+at+1%3A10m%2C+1%3A50m%2C+and+1%3A110m+scales&amp;summary=%0D%0A%0D%0ACity%20and%20town%20points%2C%20from%20Tokyo%20to%20Wasilla%2C%20Cairo%20to%20Kandahar%0D%0A%5Bdrain%20file%2039%20show%20nev_download%5D%20%5Bdrain%20file%20224%20show%20nev_download%5D%0D%0A%0D%0A%0D%0A%0D%0A%0D%0AAbout%0D%0A%0D%0APoint%20symbols%20with%20name%20attributes.%20Includes%20all%20admin-0%20and%20many%20admin-1%20capitals%2C%20major%20citie" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places&amp;source=Natural+Earth+Free+vector+and+raster+map+data+at+1%3A10m%2C+1%3A50m%2C+and+1%3A110m+scales&amp;summary=%0D%0A%0D%0ACity%20and%20town%20points%2C%20from%20Tokyo%20to%20Wasilla%2C%20Cairo%20to%20Kandahar%0D%0A%5Bdrain%20file%2039%20show%20nev_download%5D%20%5Bdrain%20file%20224%20show%20nev_download%5D%0D%0A%0D%0A%0D%0A%0D%0A%0D%0AAbout%0D%0A%0D%0APoint%20symbols%20with%20name%20attributes.%20Includes%20all%20admin-0%20and%20many%20admin-1%20capitals%2C%20major%20citie');" title="LinkedIn"><img src="http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.gif" title="LinkedIn" alt="LinkedIn" style="width: 16px; height: 16px; background: transparent url(http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.png) no-repeat; background-position:-1px -37px" class="sociable-hovers" /></a></li>
<li class="sociablelast"><a rel="nofollow" target="_blank" href="http://reddit.com/submit?url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://reddit.com/submit?url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places');" title="Reddit"><img src="http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.gif" title="Reddit" alt="Reddit" style="width: 16px; height: 16px; background: transparent url(http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.png) no-repeat; background-position:-55px -55px" class="sociable-hovers" /></a></li>
</ul>
</div>
</div>
</div>
</div>
<div id="sidebar">
<ul><li id='text-5' class='widget widget_text'><h2 class="widgettitle">Stay up to Date</h2>
<div class="textwidget"> Know when a new version of Natural Earth is released by subscribing to our <a href="http://www.naturalearthdata.com/updates/" class="up-to-date-link" >announcement list</a>.</div>
</li></ul><ul><li id='text-2' class='widget widget_text'><h2 class="widgettitle">Find a Problem?</h2>
<div class="textwidget"><div>
<div style="float:left; width:65px;"><a href="/corrections/index.php?a=add"><img class="alignleft" title="New Ticket" src="http://www.naturalearthdata.com/corrections/img/newticket.png" alt="" width="60" height="60" /></a></div><div class="textwidget" style="float:left;width:120px; font-size:1.2em; font-size-adjust:none; font-style:normal;
font-variant:normal; font-weight:normal; line-height:normal;">Submit suggestions and bug reports via our <a href="/corrections/index.php?a=add">correction system</a> and track the progress of your edits.</div>
</div></div>
</li></ul><ul><li id='text-3' class='widget widget_text'><h2 class="widgettitle">Join Our Community</h2>
<div class="textwidget"><div>
<div style="float:left; width:65px;"><a href="/forums/"><img src="http://www.naturalearthdata.com/wp-content/uploads/2009/08/green_globe_chat_bubble_562e.png" alt="forums" title="Chat in the forum!" width="50" height="50" /></a></div><div class="textwidget" style="float:left;width:120px; font-size:1.2em; font-size-adjust:none; font-style:normal;
font-variant:normal; font-weight:normal; line-height:normal;">Talk back and discuss Natural Earth in the <a href="/forums/">Forums</a>.</div>
</div></div>
</li></ul><ul><li id='text-4' class='widget widget_text'><h2 class="widgettitle">Thank You</h2>
<div class="textwidget">Our data downloads are generously hosted by Florida State University.</div>
</li></ul> </div>
</div>
<hr />
<div id="footer">
<div id="footerarea">
<div id="footerlogos">
<p>Supported by:</p>
<div class="footer-ad-box">
<a href="http://www.nacis.org" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/nacis.png" alt="NACIS" /></a>
</div>
<div class="footer-ad-box">
<a href="http://www.cartotalk.com" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/cartotalk_ad.png" alt="Cartotalk" /></a>
</div>
<div class="footer-ad-box">
<a href="http://www.mapgiving.org" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/mapgiving.png" alt="Mapgiving" /></a>
</div>
<div class="footer-ad-box">
<a href="http://www.geography.wisc.edu/cartography/" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/wisconsin.png" alt="University of Wisconsin Madison - Cartography Dept." /></a>
</div>
<div class="footer-ad-box">
<a href="http://www.shadedrelief.com" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/shaded_relief.png" alt="Shaded Relief" /></a>
</div>
<div class="footer-ad-box">
<a href="http://www.xnrproductions.com " target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/xnr.png" alt="XNR Productions" /></a>
</div>
<p style="clear:both;"></p>
<div class="footer-ad-box">
<a href="http://www.freac.fsu.edu" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/fsu.png" alt="Florida State University - FREAC" /></a>
</div>
<div class="footer-ad-box">
<a href="http://www.springercartographics.com" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/scllc.png" alt="Springer Cartographics LLC" /></a>
</div>
<div class="footer-ad-box">
<a href="http://www.washingtonpost.com" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/wpost.png" alt="Washington Post" /></a>
</div>
<div class="footer-ad-box">
<a href="http://www.redgeographics.com" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/redgeo.png" alt="Red Geographics" /></a>
</div>
<div class="footer-ad-box">
<a href="http://kelsocartography.com/blog " target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/kelso.png" alt="Kelso Cartography" /></a>
</div>
<p style="clear:both;"></p>
<div class="footer-ad-box">
<a href="http://www.avenza.com" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/avenza.png" alt="Avenza Systems Inc." /></a>
</div>
<div class="footer-ad-box">
<a href="http://www.stamen.com" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/stamen_ne_logo.png" alt="Stamen Design" /></a>
</div>
</div>
<p style="clear:both;"></p>
<span id="footerleft">
&copy; 2012. Natural Earth. All rights reserved.
</span>
<span id="footerright">
<!-- Please help promote WordPress and simpleX. Do not remove -->
<div>Powered by <a href="http://wordpress.org/">WordPress</a></div>
<div><a href="http://www.naturalearthdata.com/wp-admin">Staff Login &raquo;</a></div>
</span>
</div>
</div>
<!-- Google Analytics for WordPress | http://yoast.com/wordpress/google-analytics/ -->
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-10168306-1");
} catch(err) {}
</script>
<script src="http://www.naturalearthdata.com/wp-content/plugins/google-analytics-for-wordpress/custom_se.js" type="text/javascript"></script>
<script type="text/javascript">
try {
// Cookied already:
pageTracker._trackPageview();
} catch(err) {}
</script>
<!-- End of Google Analytics code -->
</body>
</html>
@@ -0,0 +1 @@
2.0.0
@@ -0,0 +1 @@
ISO-8859-1
Binary file not shown.
@@ -0,0 +1 @@
GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
ISO-8859-1
Binary file not shown.
@@ -0,0 +1 @@
GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
Binary file not shown.
Binary file not shown.
+6 -5
View File
@@ -25,9 +25,11 @@ import sys, os
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = []
extensions = ['IPython.sphinxext.ipython_console_highlighting',
'IPython.sphinxext.ipython_directive']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
@@ -93,10 +95,9 @@ pygments_style = 'sphinx'
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
if os.environ.get('READTHEDOCS', None) == 'True':
html_theme = 'default'
else:
html_theme = 'nature'
import sphinx_rtd_theme
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
+281
View File
@@ -0,0 +1,281 @@
Contributing to GeoPandas
=========================
(Contribution guidelines largely copied from `pandas <http://pandas.pydata.org/pandas-docs/stable/contributing.html>`_)
Overview
--------
Contributions to GeoPandas are very welcome. They are likely to
be accepted more quickly if they follow these guidelines.
At this stage of GeoPandas development, the priorities are to define a
simple, usable, and stable API and to have clean, maintainable,
readable code. Performance matters, but not at the expense of those
goals.
In general, GeoPandas follows the conventions of the pandas project
where applicable.
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/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
`getting started docs <http://about.travis-ci.org/docs/user/getting-started/>`_.
- New functionality should include tests. Please write reasonable
tests for your code and make sure that they pass on your pull request.
- Classes, methods, functions, etc. should have docstrings. The first
line of a docstring should be a standalone summary. Parameters and
return values should be ducumented explicitly.
- GeoPandas supports python 2 (2.6+) and python 3 (3.2+) with a single
code base. Use modern python idioms when possible that are
compatibile with both major versions, and use the
`six <https://pythonhosted.org/six>`_ library where helpful to smooth
over the differences. Use ``from __future__ import`` statements where
appropriate. Test code locally in both python 2 and python 3 when
possible (all supported versions will be automatically tested on
Travis CI).
- Follow PEP 8 when possible.
- Imports should be grouped with standard library imports first,
3rd-party libraries next, and geopandas imports third. Within each
grouping, imports should be alphabetized. Always use absolute
imports when possible, and explicit relative imports for local
imports when necessary in tests.
Seven Steps for Contributing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There are seven basic steps to contributing to *geopandas*:
1) Fork the *geopandas* git repository
2) Create a development environment
3) Install *geopandas* dependencies
4) Make a ``development`` build of *geopandas*
5) Make changes to code and add tests
6) Update the documentation
7) Submit a Pull Request
Each of these 7 steps is detailed below.
1) Forking the *geopandas* repository using Git
------------------------------------------------
To the new user, working with Git is one of the more daunting aspects of contributing to *geopandas**.
It can very quickly become overwhelming, but sticking to the guidelines below will help keep the process
straightforward and mostly trouble free. As always, if you are having difficulties please
feel free to ask for help.
The code is hosted on `GitHub <https://github.com/geopandas/geopandas>`_. To
contribute you will need to sign up for a `free GitHub account
<https://github.com/signup/free>`_. We use `Git <http://git-scm.com/>`_ for
version control to allow many people to work together on the project.
Some great resources for learning Git:
* Software Carpentry's `Git Tutorial <http://swcarpentry.github.io/git-novice/>`_
* `Atlassian <https://www.atlassian.com/git/tutorials/what-is-version-control>`_
* the `GitHub help pages <http://help.github.com/>`_.
* Matthew Brett's `Pydagogue <http://matthew-brett.github.com/pydagogue/>`_.
Getting started with Git
~~~~~~~~~~~~~~~~~~~~~~~~~
`GitHub has instructions <http://help.github.com/set-up-git-redirect>`__ for installing git,
setting up your SSH key, and configuring git. All these steps need to be completed before
you can work seamlessly between your local repository and GitHub.
.. _contributing.forking:
Forking
~~~~~~~~
You will need your own fork to work on the code. Go to the `geopandas project
page <https://github.com/geopandas/geopandas>`_ and hit the ``Fork`` button. You will
want to clone your fork to your machine::
git clone git@github.com:your-user-name/geopandas.git geopandas-yourname
cd geopandas-yourname
git remote add upstream git://github.com/geopandas/geopandas.git
This creates the directory `geopandas-yourname` and connects your repository to
the upstream (main project) *geopandas* repository.
The testing suite will run automatically on Travis-CI once your pull request is
submitted. However, if you wish to run the test suite on a branch prior to
submitting the pull request, then Travis-CI needs to be hooked up to your
GitHub repository. Instructions for doing so are `here
<http://about.travis-ci.org/docs/user/getting-started/>`__.
Creating a branch
~~~~~~~~~~~~~~~~~~
You want your master branch to reflect only production-ready code, so create a
feature branch for making your changes. For example::
git branch shiny-new-feature
git checkout shiny-new-feature
The above can be simplified to::
git checkout -b shiny-new-feature
This changes your working directory to the shiny-new-feature branch. Keep any
changes in this branch specific to one bug or feature so it is clear
what the branch brings to *geopandas*. You can have many shiny-new-features
and switch in between them using the git checkout command.
To update this branch, you need to retrieve the changes from the master branch::
git fetch upstream
git rebase upstream/master
This will replay your commits on top of the latest geopandas git master. If this
leads to merge conflicts, you must resolve these before submitting your pull
request. If you have uncommitted changes, you will need to ``stash`` them prior
to updating. This will effectively store your changes and they can be reapplied
after updating.
.. _contributing.dev_env:
2) Creating a development environment
---------------------------------------
A development environment is a virtual space where you can keep an independent installation of *geopandas*.
This makes it easy to keep both a stable version of python in one place you use for work, and a development
version (which you may break while playing with code) in another.
An easy way to create a *geopandas* development environment is as follows:
- Install either `Anaconda <http://docs.continuum.io/anaconda/>`_ or
`miniconda <http://conda.pydata.org/miniconda.html>`_
- Make sure that you have :ref:`cloned the repository <contributing.forking>`
- ``cd`` to the *geopandas** source directory
Tell conda to create a new environment, named ``geopandas_dev``, or any other name you would like
for this environment, by running::
conda create -n geopandas_dev
For a python 3 environment::
conda create -n geopandas_dev python=3.4
This will create the new environment, and not touch any of your existing environments,
nor any existing python installation.
To work in this environment, Windows users should ``activate`` it as follows::
activate geopandas_dev
Mac OSX and Linux users should use::
source activate geopandas_dev
You will then see a confirmation message to indicate you are in the new development environment.
To view your environments::
conda info -e
To return to you home root environment::
deactivate
See the full conda docs `here <http://conda.pydata.org/docs>`__.
At this point you can easily do a *development* install, as detailed in the next sections.
3) Installing Dependencies
--------------------------
To run *geopandas* in an development environment, you must first install
*geopandas*'s dependencies. We suggest doing so using the following commands
(executed after your development environment has been activated)::
conda install -c conda-forge fiona shapely pyproj rtree
conda install pandas
This should install all necessary dependencies.
4) Making a development build
-----------------------------
Once dependencies are in place, make an in-place build by navigating to the git
clone of the *geopandas* repository and running::
python setup.py develop
5) Making changes and writing tests
-------------------------------------
*geopandas* is serious about testing and strongly encourages contributors to embrace
`test-driven development (TDD) <http://en.wikipedia.org/wiki/Test-driven_development>`_.
This development process "relies on the repetition of a very short development cycle:
first the developer writes an (initially failing) automated test case that defines a desired
improvement or new function, then produces the minimum amount of code to pass that test."
So, before actually writing any code, you should write your tests. Often the test can be
taken from the original GitHub issue. However, it is always worth considering additional
use cases and writing corresponding tests.
Adding tests is one of the most common requests after code is pushed to *geopandas*. Therefore,
it is worth getting in the habit of writing tests ahead of time so this is never an issue.
Like many packages, *geopandas* uses the `Nose testing system
<http://nose.readthedocs.org/en/latest/index.html>`_ and the convenient
extensions in `numpy.testing
<http://docs.scipy.org/doc/numpy/reference/routines.testing.html>`_.
Writing tests
~~~~~~~~~~~~~
All tests should go into the ``tests`` directory. This folder contains many
current examples of tests, and we suggest looking to these for inspiration.
The ``.util`` module has some special ``assert`` functions that
make it easier to make statements about whether GeoSeries or GeoDataFrame
objects are equivalent. The easiest way to verify that your code is correct is to
explicitly construct the result you expect, then compare the actual result to
the expected correct result, using eg the function ``assert_geoseries_equal``.
Running the test suite
~~~~~~~~~~~~~~~~~~~~~~
The tests can then be run directly inside your Git clone (without having to
install *geopandas*) by typing::
nosetests -v
6) Updating the Documentation
-----------------------------
*geopandas* documentation resides in the `doc` folder. Changes to the docs are
make by modifying the appropriate file in the `source` folder within `doc`.
*geopandas* docs us reStructuredText syntax, `which is explained here <http://www.sphinx-doc.org/en/stable/rest.html#rst-primer>`_
and the docstrings follow the `Numpy Docstring standard <https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt>`_.
Once you have made your changes, you can build the docs by navigating to the `doc` folder and typing::
make html
The resulting html pages will be located in `doc/build/html`.
7) Submitting a Pull Request
------------------------------
Once you've made changes and pushed them to your forked repository, you then
submit a pull request to have them integrated into the *geopandas* code base.
You can find a pull request (or PR) tutorial in the `GitHub's Help Docs <https://help.github.com/articles/using-pull-requests/>`_.
+127
View File
@@ -0,0 +1,127 @@
.. currentmodule:: geopandas
.. ipython:: python
:suppress:
import geopandas as gpd
world = gpd.GeoDataFrame().from_file('_example_data/naturalearth_lowres.shp')
world = world.rename(columns={'geometry': 'borders'}).set_geometry('borders')
Data Structures
=========================================
GeoPandas implements two main data structures, a ``GeoSeries`` and a
``GeoDataFrame``. These are subclasses of pandas ``Series`` and
``DataFrame``, respectively.
GeoSeries
---------
A ``GeoSeries`` is essentially a vector where each entry in the vector
is a set of shapes corresponding to one observation. An entry may consist
of only one shape (like a single polygon) or multiple shapes that are
meant to be thought of as one observation (like the many polygons that
make up the State of Hawaii or a country like Indonesia).
*geopandas* has three basic classes of geometric objects (which are actually *shapely* objects):
* Points / Multi-Points
* Lines / Multi-Lines
* Polygons / Multi-Polygons
Note that all entries in a ``GeoSeries`` need not be of the same geometric type, although certain export operations will fail if this is not the case.
Overview of Attributes and Methods
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The ``GeoSeries`` class implements nearly all of the attributes and
methods of Shapely objects. When applied to a ``GeoSeries``, they
will apply elementwise to all geometries in the series. Binary
operations can be applied between two ``GeoSeries``, in which case the
operation is carried out elementwise. The two series will be aligned
by matching indices. Binary operations can also be applied to a
single geometry, in which case the operation is carried out for each
element of the series with that geometry. In either case, a
``Series`` or a ``GeoSeries`` will be returned, as appropriate.
A short summary of a few attributes and methods for GeoSeries is
presented here, and a full list can be found in the :doc:`all attributes and methods page <reference>`.
There is also a family of methods for creating new shapes by expanding
existing shapes or applying set-theoretic operations like "union" described
in :doc:`geometric manipulations <geometric_manipulations>`.
Attributes
^^^^^^^^^^^^^^^
* ``area``: shape area (units of projection -- see :doc:`projections <projections>`)
* ``bounds``: tuple of max and min coordinates on each axis for each shape
* ``total_bounds``: tuple of max and min coordinates on each axis for entire GeoSeries
* ``geom_type``: type of geometry.
* ``is_valid``: tests if coordinates make a shape that is reasonable geometric shape (`according to this <http://www.opengeospatial.org/standards/sfa>`_).
Basic Methods
^^^^^^^^^^^^^^
* ``distance(other)``: returns ``Series`` with minimum distance from each entry to ``other``
* ``centroid``: returns ``GeoSeries`` of centroids
* ``representative_point()``: returns ``GeoSeries`` of points that are guaranteed to be within each geometry. It does **NOT** return centroids.
* ``to_crs()``: change coordinate reference system. See :doc:`projections <projections>`
* ``plot()``: plot ``GeoSeries``. See :doc:`mapping <mapping>`.
Relationship Tests
^^^^^^^^^^^^^^^^^^^
* ``almost_equals(other)``: is shape almost the same as ``other`` (good when floating point precision issues make shapes slightly different)
* ``contains(other)``: is shape contained within ``other``
* ``intersects(other)``: does shape intersect ``other``
GeoDataFrame
------------
A ``GeoDataFrame`` is a tabular data structure that contains a ``GeoSeries``.
The most important property of a ``GeoDataFrame`` is that it always has one ``GeoSeries`` column that holds a special status. This ``GeoSeries`` is referred to as the ``GeoDataFrame``'s "geometry". When a spatial method is applied to a ``GeoDataFrame`` (or a spatial attribute like ``area`` is called), this commands will always act on the "geometry" column.
The "geometry" column -- no matter its name -- can be accessed through the ``geometry`` attribute (``gdf.geometry``), and the name of the ``geometry`` column can be found by typing ``gdf.geometry.name``.
A ``GeoDataFrame`` may also contain other columns with geometrical (shapely) objects, but only one column can be the active geometry at a time. To change which column is the active geometry column, use the ``set_geometry`` method.
An example using the ``worlds`` GeoDataFrame:
.. ipython:: python
world.head()
#Plot countries
@savefig world_borders.png width=3in
world.plot();
Currently, the column named "borders" with country borders is the active
geometry column:
.. ipython:: python
world.geometry.name
Now, we create centroids and make it the geometry:
.. ipython:: python
world['centroid_column'] = world.centroid
world = world.set_geometry('centroid_column')
@savefig world_centroids.png width=3in
world.plot();
**Note:** A ``GeoDataFrame`` keeps track of the active column by name, so if you rename the active geometry column, you must also reset the geometry::
gdf = gdf.rename(columns={'old_name': 'new_name'}).set_geometry('new_name')
**Note 2:** Somewhat confusingly, by default when you use the ``read_file`` command, the column containing spatial objects from the file is named "geometry" by default, and will be set as the active geometry column. However, despite using the same term for the name of the column and the name of the special attribute that keeps track of the active column, they are distinct. You can easily shift the active geometry column to a different ``GeoSeries`` with the ``set_geometry`` command. Further, ``gdf.geometry`` will always return the active geometry column, *not* the column named ``geometry``. If you wish to call a column named "geometry", and a different column is the active geometry column, use ``gdf['geometry']``, not ``gdf.geometry``.
Attributes and Methods
~~~~~~~~~~~~~~~~~~~~~~
Any of the attributes calls or methods described for a ``GeoSeries`` will work on a ``GeoDataFrame`` -- effectively, they are just applied to the "geometry" ``GeoSeries``.
However, ``GeoDataFrames`` also have a few extra methods for input and output which are described on the :doc:`Input and Output <io>` page and for geocoding with are described in :doc:`Geocoding <geocoding>`.
+17
View File
@@ -0,0 +1,17 @@
Geocoding
==========
[TO BE COMPLETED]
.. function:: geopandas.geocode.geocode(strings, provider='googlev3', **kwargs)
Geocode a list of strings and return a GeoDataFrame containing the
resulting points in its ``geometry`` column. Available
``provider``s include ``googlev3``, ``bing``, ``google``, ``yahoo``,
``mapquest``, and ``openmapquest``. ``**kwargs`` will be passed as
parameters to the appropriate geocoder.
Requires `geopy`_. Please consult the Terms of Service for the
chosen provider.
+243
View File
@@ -0,0 +1,243 @@
Geometric Manipulations
========================
Set-theoretic Methods
~~~~~~~~~~~~~~~~~~~~~
.. attribute:: GeoSeries.boundary
Returns a ``GeoSeries`` of lower dimensional objects representing
each geometries's set-theoretic `boundary`.
.. method:: GeoSeries.difference(other)
Returns a ``GeoSeries`` of the points in each geometry that
are not in the *other* object.
.. method:: GeoSeries.intersection(other)
Returns a ``GeoSeries`` of the intersection of each object with the `other`
geometric object.
.. method:: GeoSeries.symmetric_difference(other)
Returns a ``GeoSeries`` of the points in each object not in the `other`
geometric object, and the points in the `other` not in this object.
.. method:: GeoSeries.union(other)
Returns a ``GeoSeries`` of the union of points from each object and the
`other` geometric object.
.. attribute:: GeoSeries.unary_union
Return a geometry containing the union of all geometries in the ``GeoSeries``.
Constructive Methods
~~~~~~~~~~~~~~~~~~~~~
.. method:: GeoSeries.buffer(distance, resolution=16)
Returns a ``GeoSeries`` of geometries representing all points within a given `distance`
of each geometric object.
.. attribute:: GeoSeries.convex_hull
Returns a ``GeoSeries`` of geometries representing the smallest
convex `Polygon` containing all the points in each object unless the
number of points in the object is less than three. For two points,
the convex hull collapses to a `LineString`; for 1, a `Point`.
.. attribute:: GeoSeries.envelope
Returns a ``GeoSeries`` of geometries representing the point or
smallest rectangular polygon (with sides parallel to the coordinate
axes) that contains each object.
.. method:: GeoSeries.simplify(tolerance, preserve_topology=True)
Returns a ``GeoSeries`` containing a simplified representation of
each object.
Affine transformations
~~~~~~~~~~~~~~~~~~~~~~~
.. method:: GeoSeries.rotate(self, angle, origin='center', use_radians=False)
Rotate the coordinates of the GeoSeries.
.. method:: GeoSeries.scale(self, xfact=1.0, yfact=1.0, zfact=1.0, origin='center')
Scale the geometries of the GeoSeries along each (x, y, z) dimensio.
.. method:: GeoSeries.skew(self, angle, origin='center', use_radians=False)
Shear/Skew the geometries of the GeoSeries by angles along x and y dimensions.
.. method:: GeoSeries.translate(self, angle, origin='center', use_radians=False)
Shift the coordinates of the GeoSeries.
`Aggregating methods`
.. sourcecode:: python
>>> p1 = Polygon([(0, 0), (1, 0), (1, 1)])
>>> p2 = Polygon([(0, 0), (1, 0), (1, 1), (0, 1)])
>>> p3 = Polygon([(2, 0), (3, 0), (3, 1), (2, 1)])
>>> g = GeoSeries([p1, p2, p3])
>>> g
0 POLYGON ((0.0000000000000000 0.000000000000000...
1 POLYGON ((0.0000000000000000 0.000000000000000...
2 POLYGON ((2.0000000000000000 0.000000000000000...
dtype: object
.. image:: _static/test.png
Some geographic operations return normal pandas object. The ``area`` property of a ``GeoSeries`` will return a ``pandas.Series`` containing the area of each item in the ``GeoSeries``:
.. sourcecode:: python
>>> print g.area
0 0.5
1 1.0
2 1.0
dtype: float64
Other operations return GeoPandas objects:
.. sourcecode:: python
>>> g.buffer(0.5)
Out[15]:
0 POLYGON ((-0.3535533905932737 0.35355339059327...
1 POLYGON ((-0.5000000000000000 0.00000000000000...
2 POLYGON ((1.5000000000000000 0.000000000000000...
dtype: object
.. image:: _static/test_buffer.png
GeoPandas objects also know how to plot themselves. GeoPandas uses `descartes`_ to generate a `matplotlib`_ plot. To generate a plot of our GeoSeries, use:
.. sourcecode:: python
>>> g.plot()
GeoPandas also implements alternate constructors that can read any data format recognized by `fiona`_. To read a `file containing the boroughs of New York City`_:
.. sourcecode:: python
>>> boros = GeoDataFrame.from_file('nybb.shp')
>>> boros.set_index('BoroCode', inplace=True)
>>> boros.sort()
>>> boros
BoroName Shape_Area Shape_Leng \
BoroCode
1 Manhattan 6.364422e+08 358532.956418
2 Bronx 1.186804e+09 464517.890553
3 Brooklyn 1.959432e+09 726568.946340
4 Queens 3.049947e+09 861038.479299
5 Staten Island 1.623853e+09 330385.036974
geometry
BoroCode
1 (POLYGON ((981219.0557861328125000 188655.3157...
2 (POLYGON ((1012821.8057861328125000 229228.264...
3 (POLYGON ((1021176.4790039062500000 151374.796...
4 (POLYGON ((1029606.0765991210937500 156073.814...
5 (POLYGON ((970217.0223999023437500 145643.3322...
.. image:: _static/nyc.png
.. sourcecode:: python
>>> boros['geometry'].convex_hull
0 POLYGON ((915517.6877458114176989 120121.88125...
1 POLYGON ((1000721.5317993164062500 136681.7761...
2 POLYGON ((988872.8212280273437500 146772.03179...
3 POLYGON ((977855.4451904296875000 188082.32238...
4 POLYGON ((1017949.9776000976562500 225426.8845...
dtype: object
.. image:: _static/nyc_hull.png
To demonstrate a more complex operation, we'll generate a
``GeoSeries`` containing 2000 random points:
.. sourcecode:: python
>>> from shapely.geometry import Point
>>> xmin, xmax, ymin, ymax = 900000, 1080000, 120000, 280000
>>> xc = (xmax - xmin) * np.random.random(2000) + xmin
>>> yc = (ymax - ymin) * np.random.random(2000) + ymin
>>> pts = GeoSeries([Point(x, y) for x, y in zip(xc, yc)])
Now draw a circle with fixed radius around each point:
.. sourcecode:: python
>>> circles = pts.buffer(2000)
We can collapse these circles into a single shapely MultiPolygon
geometry with
.. sourcecode:: python
>>> mp = circles.unary_union
To extract the part of this geometry contained in each borough, we can
just use:
.. sourcecode:: python
>>> holes = boros['geometry'].intersection(mp)
.. image:: _static/holes.png
and to get the area outside of the holes:
.. sourcecode:: python
>>> boros_with_holes = boros['geometry'].difference(mp)
.. image:: _static/boros_with_holes.png
Note that this can be simplified a bit, since ``geometry`` is
available as an attribute on a ``GeoDataFrame``, and the
``intersection`` and ``difference`` methods are implemented with the
"&" and "-" operators, respectively. For example, the latter could
have been expressed simply as ``boros.geometry - mp``.
It's easy to do things like calculate the fractional area in each
borough that are in the holes:
.. sourcecode:: python
>>> holes.area / boros.geometry.area
BoroCode
1 0.602015
2 0.523457
3 0.585901
4 0.577020
5 0.559507
dtype: float64
.. _Descartes: https://pypi.python.org/pypi/descartes
.. _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::
:maxdepth: 2
+10 -3
View File
@@ -24,10 +24,18 @@ operations in python that would otherwise require a spatial database
such as PostGIS.
.. toctree::
:maxdepth: 2
:maxdepth: 2
Installation <install>
User Guide <user>
Data Structures <data_structures>
Reading and Writing Files <io>
Making Maps <mapping>
Managing Projections <projections>
Geometric Manipulations <geometric_manipulations>
Merging Data <mergingdata>
Geocoding <geocoding>
Reference to All Attributes and Methods <reference>
Contributing to GeoPandas <contributing>
About <about>
Indices and tables
@@ -36,4 +44,3 @@ Indices and tables
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
+27 -24
View File
@@ -1,16 +1,19 @@
Installation
============
Installing GeoPandas
---------------------
To install the released version, you can use pip::
pip install geopandas
or you can install the conda package from the IOOS channel::
or you can install the conda package from the conda-forge channel::
conda install -c ioos geopandas
conda install -c conda-forge geopandas
You may install the latest development version by cloning the
`GitHub`_ repository and using the setup script::
`GitHub` repository and using the setup script::
git clone https://github.com/geopandas/geopandas.git
cd geopandas
@@ -23,12 +26,10 @@ repository with::
pip install git+git://github.com/geopandas/geopandas.git
Dependencies
------------
--------------
GeoPandas supports Python versions 2.6, 2.7, and 3.3+. The required
dependencies are:
Installation via `conda` should also install all dependencies, but a complete list is as follows:
- `numpy`_
- `pandas`_ (version 0.13 or later)
@@ -41,6 +42,7 @@ Further, optional dependencies are:
- `geopy`_ 0.99 (optional; for geocoding)
- `psycopg2`_ (optional; for PostGIS connection)
- `rtree`_ (optional; spatial index to improve performance)
For plotting, these additional packages may be used:
@@ -48,39 +50,40 @@ For plotting, these additional packages may be used:
- `descartes`_
- `pysal`_
Further, `rtree`_ is an optional dependency. ``rtree`` requires the C library
`libspatialindex`_. If using brew, you can install using
``brew install Spatialindex``.
These can be installed independently via the following set of commands::
Testing
-------
conda install -c conda-forge fiona shapely pyproj rtree
conda install pandas
To run the current set of tests from the source directory, run::
nosetests -v
from a command line.
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/geopandas/geopandas
.. _numpy: http://www.numpy.org
.. _pandas: http://pandas.pydata.org
.. _shapely: http://toblerity.github.io/shapely
.. _fiona: http://toblerity.github.io/fiona
.. _Descartes: https://pypi.python.org/pypi/descartes
.. _matplotlib: http://matplotlib.org
.. _geopy: https://github.com/geopy/geopy
.. _six: https://pythonhosted.org/six
.. _psycopg2: https://pypi.python.org/pypi/psycopg2
.. _pysal: http://pysal.org
.. _pyproj: https://github.com/jswhit/pyproj
.. _rtree: https://github.com/Toblerity/rtree
.. _libspatialindex: https://github.com/libspatialindex/libspatialindex
.. _Travis CI: https://travis-ci.org/geopandas/geopandas
.. toctree::
:maxdepth: 2
+28
View File
@@ -0,0 +1,28 @@
Reading and Writing Files
=========================================
Reading Spatial Data
---------------------
*geopandas* can read almost any vector-based spatial data format including ESRI shapefile, GeoJSON files and more using the command::
gpd.read_file()
which returns a GeoDataFrame object. (This is possible because *geopandas* makes use of the great `fiona <http://toblerity.org/fiona/manual.html>`_ library, which in turn makes use of a massive open-source program called `GDAL/OGR <http://www.gdal.org/>`_ designed to facilitate spatial data transformations).
Any arguments passed to ``read_file()`` after the file name will be passed directly to ``fiona.open``, which does the actual data importation. In general, ``read_file`` is pretty smart and should do what you want without extra arguments, but for more help, type::
import fiona; help(fiona.open)
Among other things, one can explicitly set the driver (shapefile, GeoJSON) with the ``driver`` keyword, or pick a single layer from a multi-layered file with the ``layer`` keyword.
*geopandas* can also get data from a PostGIS database using the ``read_postgis()`` command.
Writing Spatial Data
---------------------
GeoDataFrames can be exported to many different standard formats using the ``GeoDataFrame.to_file()`` method. For a full list of supported formats, type ``import fiona; fiona.supported_drivers``.
+115
View File
@@ -0,0 +1,115 @@
.. currentmodule:: geopandas
.. ipython:: python
:suppress:
import geopandas as gpd
world = gpd.GeoDataFrame().from_file('_example_data/naturalearth_lowres.shp')
cities = gpd.GeoDataFrame().from_file('_example_data/naturalearth_cities.shp')
Mapping Tools
=========================================
*geopandas* provides a high-level interface to the ``matplotlib`` library for making maps. Mapping shapes is as easy as using the ``plot()`` method on a ``GeoSeries`` or ``GeoDataFrame``.
.. ipython:: python
# Examine country GeoDataFrame
world.head()
# Basic plot, random colors
@savefig world_randomcolors.png width=5in
world.plot();
Note that in general, any options one can pass to `pyplot <http://matplotlib.org/api/pyplot_api.html>`_ in ``matplotlib`` (or `style options that work for lines <http://matplotlib.org/api/lines_api.html>`_) can be passed to the ``plot()`` method.
Chloropleth Maps
-----------------
*geopandas* makes it easy to create Chloropleth maps (maps where the color of each shape is based on the value of an associated variable). Simply use the plot command with the ``column`` argument set to the column whose values you want used to assign colors.
.. ipython:: python
# Plot by GDP per capta
world = world[(world.pop_est>0) & (world.name!="Antarctica")]
world['gdp_per_cap'] = world.gdp_md_est / world.pop_est
@savefig world_gdp_per_cap.png width=5in
world.plot(column='gdp_per_cap');
Choosing colors
~~~~~~~~~~~~~~~~
One can also modify the colors used by ``plot`` with the ``cmap`` option (for a full list of colormaps, see the `matplotlib website <http://matplotlib.org/users/colormaps.html>`_):
.. ipython:: python
@savefig world_gdp_per_cap_red.png width=5in
world.plot(column='gdp_per_cap', cmap='OrRd');
The way color maps are scaled can also be manipulated with the ``scheme`` option (if you have ``pysal`` installed, which can be accomplished via ``conda install pysal``). By default, ``scheme`` is set to 'equal_intervals', but it can also be adjusted to any other `pysal option <http://pysal.org/1.2/library/esda/mapclassify.html>`_, like 'quantiles', 'percentiles', etc.
.. ipython:: python
@savefig world_gdp_per_cap_quantiles.png width=5in
world.plot(column='gdp_per_cap', cmap='OrRd', scheme='quantiles');
Maps with Layers
-----------------
There are two strategies for making a map with multiple layers -- one more succinct, and one that is a littel more flexible.
Before combining maps, however, remember to always ensure they share a common CRS (so they will align).
.. ipython:: python
# Look at capitals
# Note use of standard `pyplot` line style options
@savefig capitals.png width=5in
cities.plot(marker='*', color='green', markersize=5);
# Check crs
cities = cities.to_crs(world.crs)
# Now we can overlay over country outlines
# And yes, there are lots of island capitals
# apparently in the middle of the ocean!
**Method 1**
.. ipython:: python
base = world.plot(color='white')
@savefig capitals_over_countries_1.png width=5in
cities.plot(ax=base, marker='o', color='red', markersize=5);
**Method 2: Using matplotlib objects**
.. ipython:: python
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
# set aspect to equal. This is done automatically
# when using *geopandas* plot on it's own, but not when
# working with pyplot directly.
ax.set_aspect('equal')
world.plot(ax=ax, color='white')
cities.plot(ax=ax, marker='o', color='red', markersize=5)
@savefig capitals_over_countries_2.png width=5in
plt.show();
Other Resources
-----------------
Links to jupyter Notebooks for different mapping tasks:
`Making Heat Maps <http://nbviewer.jupyter.org/gist/perrygeo/c426355e40037c452434>`_
+15
View File
@@ -0,0 +1,15 @@
Merging Data
=========================================
Attribute Joins
----------------
[TO BE COMPLETED -- EXAMPLES OF JOINING GDF WITH PANDAS DATAFRAME]
Spatial Joins
----------------
[TO BE COMPLETED -- EXAMPLES OF SPATIAL JOINS]
+71
View File
@@ -0,0 +1,71 @@
.. currentmodule:: geopandas
.. ipython:: python
:suppress:
import geopandas as gpd
world = gpd.GeoDataFrame().from_file('_example_data/naturalearth_lowres.shp')
Managing Projections
=========================================
Coordinate Reference Systems
-----------------------------
CRS are important because the geometric shapes in a GeoSeries or GeoDataFrame object are simply a collection of coordinates in an arbitrary space. A CRS tells Python how those coordinates related to places on the Earth.
CRS are referred to using codes called `proj4 strings <https://en.wikipedia.org/wiki/PROJ.4>`_. You can find the codes for most commonly used projections from `www.spatialreference.org <http://spatialreference.org/>`_ or `remotesensing.org <http://www.remotesensing.org/geotiff/proj_list/>`_.
The same CRS can often be referred to in many ways. For example, one of the most commonly used CRS is the WGS84 latitude-longitude projection. One `proj4` representation of this projection is: ``"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"``. But common projections can also be referred to by `EPSG` codes, so this same projection can also called using the `proj4` string ``"+init=epsg:4326"``.
*geopandas* can accept lots of representations of CRS, including the `proj4` string itself (``"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"``) or parameters broken out in a dictionary: ``{'proj': 'latlong', 'ellps': 'WGS84', 'datum': 'WGS84', 'no_defs': True}``). In addition, some functions will take `EPSG` codes directly.
For reference, a few very common projections and their proj4 strings:
* WGS84 Latitude/Longitude: ``"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"`` or ``"+init=epsg:4326"``
* UTM Zones (North): ``"+proj=utm +zone=33 +ellps=WGS84 +datum=WGS84 +units=m +no_defs"``
* UTM Zones (South): ``"+proj=utm +zone=33 +ellps=WGS84 +datum=WGS84 +units=m +no_defs +south"``
Setting a Projection
----------------------
There are two relevant operations for projections: setting a projection and re-projecting.
Setting a projection may be necessary when for some reason *geopandas* has coordinate data (x-y values), but no information about how those coordinates refer to locations in the real world. Setting a projection is how one tells *geopandas* how to interpret coordinates. If no CRS is set, *geopandas* geometry operations will still work, but coordinate transformations will not be possible and exported files may not be interpreted correctly by other software.
Be aware that **most of the time** you don't have to set a projection. Data loaded from a reputable source (using the ``from_file()`` command) *should* always include projection information. You can see an objects current CRS through the ``crs`` attribute: ``my_geoseries.crs``.
From time to time, however, you may get data that does not include a projection. In this situation, you have to set the CRS so *geopandas* knows how to interpret the coordinates.
For example, if you convert a spreadsheet of latitudes and longitudes into a GeoSeries by hand, you would set the projection by assigning the WGS84 latitude-longitude CRS to the ``crs`` attribute:
.. sourcecode:: python
my_geoseries.crs = {'init' :'epsg:4326'}
Re-Projecting
----------------
Re-projecting is the process of changing the representation of locations from one coordinate system to another. All projections of locations on the Earth into a two-dimensional plane `are distortions <https://en.wikipedia.org/wiki/Map_projection#Which_projection_is_best.3F>`_, the projection that is best for your application may be different from the projection associated with the data you import. In these cases, data can be re-projected using the ``to_crs`` command:
.. ipython:: python
# Check original projection
# (it's Platte Carre! x-y are long and lat)
world.crs
# Visualize
@savefig world_starting.png width=3in
world.plot();
# Reproject to Mercator (after dropping Antartica)
world = world[(world.name != "Antarctica") & (world.name != "Fr. S. Antarctic Lands")]
world = world.to_crs({'init': 'epsg:3395'}) # world.to_crs(epsg=3395) would also work
@savefig world_reproj.png width=3in
world.plot();
@@ -1,24 +1,7 @@
GeoPandas User Guide
====================
GeoPandas implements two main data structures, a ``GeoSeries`` and a
``GeoDataFrame``. These are subclasses of pandas ``Series`` and
``DataFrame``, respectively.
GeoSeries
---------
A ``GeoSeries`` contains a sequence of geometries.
The ``GeoSeries`` class implements nearly all of the attributes and
methods of Shapely objects. When applied to a ``GeoSeries``, they
will apply elementwise to all geometries in the series. Binary
operations can be applied between two ``GeoSeries``, in which case the
operation is carried out elementwise. The two series will be aligned
by matching indices. Binary operations can also be applied to a
single geometry, in which case the operation is carried out for each
element of the series with that geometry. In either case, a
``Series`` or a ``GeoSeries`` will be returned, as appropriate.
Reference
===========================
The following Shapely methods and attributes are available on
``GeoSeries`` objects:
@@ -327,174 +310,3 @@ 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
do so.
Geopandas functions
-------------------
.. function:: geopandas.geocode.geocode(strings, provider='googlev3', **kwargs)
Geocode a list of strings and return a GeoDataFrame containing the
resulting points in its ``geometry`` column. Available
``provider``s include ``googlev3``, ``bing``, ``google``, ``yahoo``,
``mapquest``, and ``openmapquest``. ``**kwargs`` will be passed as
parameters to the appropriate geocoder.
Requires `geopy`_. Please consult the Terms of Service for the
chosen provider.
Examples
--------
.. sourcecode:: python
>>> p1 = Polygon([(0, 0), (1, 0), (1, 1)])
>>> p2 = Polygon([(0, 0), (1, 0), (1, 1), (0, 1)])
>>> p3 = Polygon([(2, 0), (3, 0), (3, 1), (2, 1)])
>>> g = GeoSeries([p1, p2, p3])
>>> g
0 POLYGON ((0.0000000000000000 0.000000000000000...
1 POLYGON ((0.0000000000000000 0.000000000000000...
2 POLYGON ((2.0000000000000000 0.000000000000000...
dtype: object
.. image:: _static/test.png
Some geographic operations return normal pandas object. The ``area`` property of a ``GeoSeries`` will return a ``pandas.Series`` containing the area of each item in the ``GeoSeries``:
.. sourcecode:: python
>>> print g.area
0 0.5
1 1.0
2 1.0
dtype: float64
Other operations return GeoPandas objects:
.. sourcecode:: python
>>> g.buffer(0.5)
Out[15]:
0 POLYGON ((-0.3535533905932737 0.35355339059327...
1 POLYGON ((-0.5000000000000000 0.00000000000000...
2 POLYGON ((1.5000000000000000 0.000000000000000...
dtype: object
.. image:: _static/test_buffer.png
GeoPandas objects also know how to plot themselves. GeoPandas uses `descartes`_ to generate a `matplotlib`_ plot. To generate a plot of our GeoSeries, use:
.. sourcecode:: python
>>> g.plot()
GeoPandas also implements alternate constructors that can read any data format recognized by `fiona`_. To read a `file containing the boroughs of New York City`_:
.. sourcecode:: python
>>> boros = GeoDataFrame.from_file('nybb.shp')
>>> boros.set_index('BoroCode', inplace=True)
>>> boros.sort()
>>> boros
BoroName Shape_Area Shape_Leng \
BoroCode
1 Manhattan 6.364422e+08 358532.956418
2 Bronx 1.186804e+09 464517.890553
3 Brooklyn 1.959432e+09 726568.946340
4 Queens 3.049947e+09 861038.479299
5 Staten Island 1.623853e+09 330385.036974
geometry
BoroCode
1 (POLYGON ((981219.0557861328125000 188655.3157...
2 (POLYGON ((1012821.8057861328125000 229228.264...
3 (POLYGON ((1021176.4790039062500000 151374.796...
4 (POLYGON ((1029606.0765991210937500 156073.814...
5 (POLYGON ((970217.0223999023437500 145643.3322...
.. image:: _static/nyc.png
.. sourcecode:: python
>>> boros['geometry'].convex_hull
0 POLYGON ((915517.6877458114176989 120121.88125...
1 POLYGON ((1000721.5317993164062500 136681.7761...
2 POLYGON ((988872.8212280273437500 146772.03179...
3 POLYGON ((977855.4451904296875000 188082.32238...
4 POLYGON ((1017949.9776000976562500 225426.8845...
dtype: object
.. image:: _static/nyc_hull.png
To demonstrate a more complex operation, we'll generate a
``GeoSeries`` containing 2000 random points:
.. sourcecode:: python
>>> from shapely.geometry import Point
>>> xmin, xmax, ymin, ymax = 900000, 1080000, 120000, 280000
>>> xc = (xmax - xmin) * np.random.random(2000) + xmin
>>> yc = (ymax - ymin) * np.random.random(2000) + ymin
>>> pts = GeoSeries([Point(x, y) for x, y in zip(xc, yc)])
Now draw a circle with fixed radius around each point:
.. sourcecode:: python
>>> circles = pts.buffer(2000)
We can collapse these circles into a single shapely MultiPolygon
geometry with
.. sourcecode:: python
>>> mp = circles.unary_union
To extract the part of this geometry contained in each borough, we can
just use:
.. sourcecode:: python
>>> holes = boros['geometry'].intersection(mp)
.. image:: _static/holes.png
and to get the area outside of the holes:
.. sourcecode:: python
>>> boros_with_holes = boros['geometry'].difference(mp)
.. image:: _static/boros_with_holes.png
Note that this can be simplified a bit, since ``geometry`` is
available as an attribute on a ``GeoDataFrame``, and the
``intersection`` and ``difference`` methods are implemented with the
"&" and "-" operators, respectively. For example, the latter could
have been expressed simply as ``boros.geometry - mp``.
It's easy to do things like calculate the fractional area in each
borough that are in the holes:
.. sourcecode:: python
>>> holes.area / boros.geometry.area
BoroCode
1 0.602015
2 0.523457
3 0.585901
4 0.577020
5 0.559507
dtype: float64
.. _Descartes: https://pypi.python.org/pypi/descartes
.. _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::
:maxdepth: 2
+1 -1
View File
@@ -14,7 +14,7 @@ from geopandas import GeoSeries, GeoDataFrame
np.random.seed(1)
DPI = 100
# http://www.nyc.gov/html/dcp/download/bytes/nybb_14aav.zip
# http://www1.nyc.gov/assets/planning/download/zip/data-maps/open-data/nybb_16a.zip
boros = GeoDataFrame.from_file('nybb.shp')
boros.set_index('BoroCode', inplace=True)
boros.sort()
+9
View File
@@ -350,6 +350,12 @@ class GeoDataFrame(GeoPandasBase, DataFrame):
joining points are assumed to be lines in the current
projection, not geodesics. Objects crossing the dateline (or
other projection boundary) will have undesirable behavior.
`to_crs` passes the `crs` argument to the `Proj` function from the
`pyproj` library (with the option `preserve_units=True`). It can
therefore accept proj4 projections in any format
supported by `Proj`, including dictionaries, or proj4 strings.
"""
if inplace:
df = self
@@ -429,8 +435,11 @@ class GeoDataFrame(GeoPandasBase, DataFrame):
return GeoDataFrame(data).__finalize__(self)
def plot(self, *args, **kwargs):
return plot_dataframe(self, *args, **kwargs)
plot.__doc__ = plot_dataframe.__doc__
def _dataframe_set_geometry(self, col, drop=False, inplace=False, crs=None):
if inplace:
+21 -3
View File
@@ -1,4 +1,5 @@
from functools import partial
import json
from warnings import warn
import numpy as np
@@ -238,9 +239,10 @@ class GeoSeries(GeoPandasBase, Series):
else:
return False
def plot(self, *args, **kwargs):
return plot_series(self, *args, **kwargs)
plot.__doc__ = plot_series.__doc__
#
# Additional methods
@@ -254,6 +256,12 @@ class GeoSeries(GeoPandasBase, Series):
joining points are assumed to be lines in the current
projection, not geodesics. Objects crossing the dateline (or
other projection boundary) will have undesirable behavior.
`to_crs` passes the `crs` argument to the `Proj` function from the
`pyproj` library (with the option `preserve_units=True`). It can
therefore accept proj4 projections in any format
supported by `Proj`, including dictionaries, or proj4 strings.
"""
from fiona.crs import from_epsg
if self.crs is None:
@@ -264,8 +272,8 @@ class GeoSeries(GeoPandasBase, Series):
crs = from_epsg(epsg)
except TypeError:
raise TypeError('Must set either crs or epsg for output.')
proj_in = pyproj.Proj(preserve_units=True, **self.crs)
proj_out = pyproj.Proj(preserve_units=True, **crs)
proj_in = pyproj.Proj(self.crs, preserve_units=True)
proj_out = pyproj.Proj(crs, preserve_units=True)
project = partial(pyproj.transform, proj_in, proj_out)
result = self.apply(lambda geom: transform(project, geom))
result.__class__ = GeoSeries
@@ -273,6 +281,16 @@ class GeoSeries(GeoPandasBase, Series):
result._invalidate_sindex()
return result
def to_json(self, **kwargs):
"""
Returns a GeoJSON string representation of the GeoSeries.
Parameters
----------
*kwargs* that will be passed to json.dumps().
"""
return json.dumps(self.__geo_interface__, **kwargs)
#
# Implement standard operators for GeoSeries
#
+3 -2
View File
@@ -13,8 +13,9 @@ def read_file(filename, **kwargs):
Returns a GeoDataFrame from a file.
*filename* is either the absolute or relative path to the file to be
opened and *kwargs* are keyword args to be passed to the method when
opening the file.
opened and *kwargs* are keyword args to be passed to the `open` method
in the fiona library when opening the file. For more information on
possible keywords, type: ``import fiona; help(fiona.open)``
"""
bbox = kwargs.pop('bbox', None)
with fiona.open(filename, **kwargs) as f:
@@ -2,23 +2,22 @@ from __future__ import absolute_import
import fiona
from geopandas import GeoDataFrame, read_postgis, read_file
import tests.util
from .util import PANDAS_NEW_SQL_API, unittest
from geopandas import read_postgis, read_file
from geopandas.tests.util import download_nybb, connect, create_db, \
PANDAS_NEW_SQL_API, unittest, validate_boro_df
class TestIO(unittest.TestCase):
def setUp(self):
nybb_filename = tests.util.download_nybb()
path = '/nybb_14a_av/nybb.shp'
nybb_filename, nybb_zip_path = download_nybb()
vfs = 'zip://' + nybb_filename
self.df = read_file(path, vfs=vfs)
with fiona.open(path, vfs=vfs) as f:
self.df = read_file(nybb_zip_path, vfs=vfs)
with fiona.open(nybb_zip_path, vfs=vfs) as f:
self.crs = f.crs
def test_read_postgis_default(self):
con = tests.util.connect('test_geopandas')
if con is None or not tests.util.create_db(self.df):
con = connect('test_geopandas')
if con is None or not create_db(self.df):
raise unittest.case.SkipTest()
try:
@@ -30,11 +29,11 @@ class TestIO(unittest.TestCase):
con = con.connect()
con.close()
tests.util.validate_boro_df(self, df)
validate_boro_df(self, df)
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):
con = connect('test_geopandas')
if con is None or not create_db(self.df):
raise unittest.case.SkipTest()
try:
@@ -49,9 +48,9 @@ class TestIO(unittest.TestCase):
con = con.connect()
con.close()
tests.util.validate_boro_df(self, df)
validate_boro_df(self, df)
def test_read_file(self):
df = self.df.rename(columns=lambda x: x.lower())
tests.util.validate_boro_df(self, df)
validate_boro_df(self, df)
self.assert_(df.crs == self.crs)

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

@@ -11,7 +11,7 @@ from geopandas import GeoSeries
from geopandas.tools import geocode, reverse_geocode
from geopandas.tools.geocoding import _prepare_geocode_result
from .util import unittest, mock, assert_geoseries_equal
from geopandas.tests.util import unittest, mock, assert_geoseries_equal
def _skip_if_no_geopy():
@@ -12,8 +12,8 @@ from shapely.geometry import Point, Polygon
import fiona
from geopandas import GeoDataFrame, read_file, GeoSeries
from .util import unittest, download_nybb, assert_geoseries_equal, connect, \
create_db, validate_boro_df, PANDAS_NEW_SQL_API
from geopandas.tests.util import assert_geoseries_equal, connect, create_db, \
download_nybb, PACKAGE_DIR, PANDAS_NEW_SQL_API, unittest, validate_boro_df
class TestDataFrame(unittest.TestCase):
@@ -21,10 +21,10 @@ class TestDataFrame(unittest.TestCase):
def setUp(self):
N = 10
nybb_filename = download_nybb()
nybb_filename, nybb_zip_path = download_nybb()
self.df = read_file('/nybb_14a_av/nybb.shp', vfs='zip://' + nybb_filename)
with fiona.open('/nybb_14a_av/nybb.shp', vfs='zip://' + nybb_filename) as f:
self.df = read_file(nybb_zip_path, vfs='zip://' + nybb_filename)
with fiona.open(nybb_zip_path, vfs='zip://' + nybb_filename) as f:
self.schema = f.schema
self.tempdir = tempfile.mkdtemp()
self.boros = self.df['BoroName']
@@ -32,7 +32,7 @@ class TestDataFrame(unittest.TestCase):
self.df2 = GeoDataFrame([
{'geometry': Point(x, y), 'value1': x + y, 'value2': x * y}
for x, y in zip(range(N), range(N))], crs=self.crs)
self.df3 = read_file('examples/null_geom.geojson')
self.df3 = read_file(os.path.join(PACKAGE_DIR, 'examples', 'null_geom.geojson'))
self.line_paths = self.df3['Name']
def tearDown(self):
@@ -373,8 +373,8 @@ class TestDataFrame(unittest.TestCase):
self.assertTrue(all(df2['geometry'].geom_almost_equals(utm['geometry'], decimal=2)))
def test_from_features(self):
nybb_filename = download_nybb()
with fiona.open('/nybb_14a_av/nybb.shp',
nybb_filename, nybb_zip_path = download_nybb()
with fiona.open(nybb_zip_path,
vfs='zip://' + nybb_filename) as f:
features = list(f)
crs = f.crs
@@ -14,10 +14,11 @@ from shapely.ops import unary_union
from geopandas import GeoSeries, GeoDataFrame
from geopandas.base import GeoPandasBase
from .util import (
from geopandas.tests.util import (
unittest, geom_equals, geom_almost_equals, assert_geoseries_equal
)
class TestGeomMethods(unittest.TestCase):
def setUp(self):
@@ -1,16 +1,16 @@
from __future__ import absolute_import
import os
import json
import shutil
import tempfile
import numpy as np
from numpy.testing import assert_array_equal
from pandas import Series
from shapely.geometry import (Polygon, Point, LineString,
MultiPoint, MultiLineString, MultiPolygon)
from shapely.geometry.base import BaseGeometry
from geopandas import GeoSeries
from .util import unittest, geom_equals, geom_almost_equals
from geopandas.tests.util import unittest, geom_equals
class TestSeries(unittest.TestCase):
@@ -116,6 +116,12 @@ class TestSeries(unittest.TestCase):
self.assertTrue(all(self.g3.geom_equals(s)))
# TODO: compare crs
def test_to_json(self):
"""Test whether GeoSeries.to_json works and returns an actual json file."""
json_str = self.g3.to_json()
json_dict = json.loads(json_str)
# TODO : verify the output is a valid GeoJSON.
def test_representative_point(self):
self.assertTrue(np.alltrue(self.g1.contains(self.g1.representative_point())))
self.assertTrue(np.alltrue(self.g2.contains(self.g2.representative_point())))
@@ -151,5 +157,28 @@ class TestSeries(unittest.TestCase):
self.assertEqual(len(self.g1.__geo_interface__['features']),
self.g1.shape[0])
def test_proj4strings(self):
# As string
reprojected = self.g3.to_crs('+proj=utm +zone=30N')
reprojected_back = reprojected.to_crs(epsg=4326)
self.assertTrue(np.alltrue(self.g3.geom_almost_equals(reprojected_back)))
# As dict
reprojected = self.g3.to_crs({'proj': 'utm', 'zone': '30N'})
reprojected_back = reprojected.to_crs(epsg=4326)
self.assertTrue(np.alltrue(self.g3.geom_almost_equals(reprojected_back)))
# Set to equivalent string, convert, compare to original
copy = self.g3.copy()
copy.crs = '+init=epsg:4326'
reprojected = copy.to_crs({'proj': 'utm', 'zone': '30N'})
reprojected_back = reprojected.to_crs(epsg=4326)
self.assertTrue(np.alltrue(self.g3.geom_almost_equals(reprojected_back)))
# Conversions by different format
reprojected_string = self.g3.to_crs('+proj=utm +zone=30N')
reprojected_dict = self.g3.to_crs({'proj': 'utm', 'zone': '30N'})
self.assertTrue(np.alltrue(reprojected_string.geom_almost_equals(reprojected_dict)))
if __name__ == '__main__':
unittest.main()
@@ -1,10 +1,13 @@
from __future__ import absolute_import
import tempfile
import shutil
from shapely.geometry import Point
from geopandas import GeoDataFrame, read_file
from geopandas.tools import overlay
from .util import unittest, download_nybb
from geopandas.tests.util import unittest, download_nybb
class TestDataFrame(unittest.TestCase):
@@ -12,9 +15,9 @@ class TestDataFrame(unittest.TestCase):
def setUp(self):
N = 10
nybb_filename = download_nybb()
nybb_filename, nybb_zip_path = download_nybb()
self.polydf = read_file('/nybb_14a_av/nybb.shp', vfs='zip://' + nybb_filename)
self.polydf = read_file(nybb_zip_path, vfs='zip://' + nybb_filename)
self.tempdir = tempfile.mkdtemp()
self.crs = {'init': 'epsg:4326'}
b = [int(x) for x in self.polydf.total_bounds]
@@ -1,13 +1,7 @@
import shutil
import tempfile
import numpy as np
from numpy.testing import assert_array_equal
from pandas import Series, read_csv
from shapely.geometry import (Polygon, Point, LineString,
MultiPoint, MultiLineString, MultiPolygon)
from shapely.geometry.base import BaseGeometry
from shapely.geometry import Polygon, Point
from geopandas import GeoSeries, GeoDataFrame, base, read_file
from .util import unittest, geom_equals, geom_almost_equals
from geopandas.tests.util import unittest, download_nybb
@unittest.skipIf(not base.HAS_SINDEX, 'Rtree absent, skipping')
@@ -85,9 +79,8 @@ class TestFrameSindex(unittest.TestCase):
class TestJoinSindex(unittest.TestCase):
def setUp(self):
self.boros = read_file(
"/nybb_14a_av/nybb.shp",
vfs="zip://examples/nybb_14aav.zip")
nybb_filename, nybb_zip_path = download_nybb()
self.boros = read_file(nybb_zip_path, vfs='zip://' + nybb_filename)
def test_merge_geo(self):
# First check that we gets hits from the boros frame.
@@ -122,4 +115,3 @@ class TestJoinSindex(unittest.TestCase):
self.assertEqual(
[merged.ix[hit.object]['BoroName'] for hit in hits],
['Bronx', 'Queens'])
@@ -5,7 +5,7 @@ from shapely.geometry import Point
from pandas import Series, DataFrame
from geopandas import GeoSeries, GeoDataFrame
from .util import unittest
from geopandas.tests.util import unittest
OLD_PANDAS = issubclass(Series, np.ndarray)
+22 -14
View File
@@ -1,17 +1,22 @@
import io
import os.path
import sys
import zipfile
from six.moves.urllib.request import urlopen
from pandas.util.testing import assert_isinstance
from geopandas import GeoDataFrame, GeoSeries
HERE = os.path.abspath(os.path.dirname(__file__))
PACKAGE_DIR = os.path.dirname(os.path.dirname(HERE))
# Compatibility layer for Python 2.6: try loading unittest2
import sys
if sys.version_info[:2] == (2, 6):
try:
import unittest2 as unittest
except ImportError:
import unittest
else:
import unittest
@@ -36,16 +41,26 @@ else:
def download_nybb():
""" Returns the path to the NYC boroughs file. Downloads if necessary. """
""" Returns the path to the NYC boroughs file. Downloads if necessary.
returns tuple (zip file name, shapefile's name and path within zip file)"""
# Data from http://www.nyc.gov/html/dcp/download/bytes/nybb_14aav.zip
# saved as geopandas/examples/nybb_14aav.zip.
filename = 'nybb_14aav.zip'
full_path_name = os.path.join('examples', filename)
filename = 'nybb_16a.zip'
full_path_name = os.path.join(PACKAGE_DIR, 'examples', filename)
if not os.path.exists(full_path_name):
with io.open(full_path_name, 'wb') as f:
response = urlopen('http://www.nyc.gov/html/dcp/download/bytes/{0}'.format(filename))
response = urlopen('http://www1.nyc.gov/assets/planning/download/zip/data-maps/open-data/{0}'.format(filename))
f.write(response.read())
return full_path_name
shp_zip_path = None
zf = zipfile.ZipFile(full_path_name, 'r')
# finds path name in zip file
for zip_filename_path in zf.namelist():
if zip_filename_path.endswith('nybb.shp'):
break
return full_path_name, ('/' + zip_filename_path)
def validate_boro_df(test, df):
@@ -149,13 +164,6 @@ def geom_almost_equals(this, that):
return (this.geom_almost_equals(that) |
(this.is_empty & that.is_empty)).all()
# TODO: Remove me when standardizing on pandas 0.13, which already includes
# this test util.
def assert_isinstance(obj, klass_or_tuple):
assert isinstance(obj, klass_or_tuple), "type: %r != %r" % (
type(obj).__name__,
getattr(klass_or_tuple, '__name__',
klass_or_tuple))
def assert_geoseries_equal(left, right, check_dtype=False,
check_index_type=False,
View File
@@ -1,12 +1,13 @@
from __future__ import absolute_import
import tempfile
import shutil
import numpy as np
from shapely.geometry import Point
from geopandas import GeoDataFrame, read_file, base
from .util import unittest, download_nybb
from geopandas.tests.util import unittest, download_nybb
from geopandas.tools import sjoin
@@ -14,8 +15,8 @@ from geopandas.tools import sjoin
class TestSpatialJoin(unittest.TestCase):
def setUp(self):
nybb_filename = download_nybb()
self.polydf = read_file('/nybb_14a_av/nybb.shp', vfs='zip://' + nybb_filename)
nybb_filename, nybb_zip_path = download_nybb()
self.polydf = read_file(nybb_zip_path, vfs='zip://' + nybb_filename)
self.tempdir = tempfile.mkdtemp()
self.crs = {'init': 'epsg:4326'}
N = 20
@@ -55,7 +56,7 @@ class TestSpatialJoin(unittest.TestCase):
# points within polygons
df = sjoin(self.pointdf, self.polydf, how="left", op="within")
self.assertEquals(df.shape, (21,8))
self.assertAlmostEquals(df.ix[1]['Shape_Leng'], 330454.175933)
self.assertEquals(df.ix[1]['BoroName'], 'Staten Island')
# points contain polygons? never happens so we should have nulls
df = sjoin(self.pointdf, self.polydf, how="left", op="contains")
@@ -1,18 +1,20 @@
from __future__ import absolute_import
from shapely.geometry import Point, MultiPoint, LineString
from geopandas import GeoSeries
from geopandas.tools import collect
from .util import unittest
from geopandas.tests.util import unittest
class TestTools(unittest.TestCase):
def setUp(self):
self.p1 = Point(0,0)
self.p2 = Point(1,1)
self.p3 = Point(2,2)
self.p1 = Point(0, 0)
self.p2 = Point(1, 1)
self.p3 = Point(2, 2)
self.mpc = MultiPoint([self.p1, self.p2, self.p3])
self.mp1 = MultiPoint([self.p1, self.p2])
self.line1 = LineString([(3,3), (4,4)])
self.line1 = LineString([(3, 3), (4, 4)])
def test_collect_single(self):
result = collect(self.p1)
+5
View File
@@ -0,0 +1,5 @@
conda:
file: doc/environment.yml
python:
version: 3
setup_py_install: true
+2
View File
@@ -0,0 +1,2 @@
[bdist_wheel]
universal = 1