Dernièrement, j'utilise les classes de projection OGR fournies avec ogr / gdal, mais pyproj m'a été recommandé, alors j'ai pensé essayer. Pour m'aider à décider si je devais faire le changement, j'ai fait un test de vitesse. Ce qui suit est un petit exemple (presque) reproductible que j'ai trouvé pour tester les deux. Je ne sais pas si ce test est totalement équitable, donc les commentaires et recommandations sont les bienvenus!
Les importations d'abord, pour être sûrs de commencer sur un pied d'égalité:
from pandas import Series # This is what our geometries are stored in
from shapely import wkb
import functools
from shapely.geometry import shape
from osgeo import ogr
# The following two imports are the important ones
from pyproj import Proj, transform
from osgeo.osr import SpatialReference, CoordinateTransformation
Parce que je stocke les géométries galbées dans une «série» de pandas, les fonctions doivent fonctionner Series.apply()
. Ici, je définis deux fonctions (une utilisant 'ogr.osr' et une utilisant 'pyproj') pour effectuer des transformations de coordonnées dans un appel à Series.apply()
:
def transform_osr(geoms, origin, target):
target_crs = SpatialReference()
target_crs.ImportFromEPSG(origin)
origin_crs = SpatialReference()
origin_crs.ImportFromEPSG(origin)
transformer = CoordinateTransformation(origin_crs, target_crs)
def trans(geom):
g = ogr.CreateGeometryFromWkb(geom.wkb)
if g.Transform(transformer):
raise Exception("Ahhhh!")
g = wkb.loads(g.ExportToWkb())
return g
return geoms.apply(trans)
def transform_pyproj(geoms, origin, target):
target = Proj(init="epsg:%s" % target)
origin = Proj(init="epsg:%s" % origin)
transformer = functools.partial(transform, origin, target)
def trans(geom):
interface = geom.__geo_interface__
geom_type = interface['type']
coords = interface['coordinates']
result = apply_to_coord_pairs(transformer, coords)
return shape({'coordinates':result, 'type':geom_type})
def apply_to_coord_pairs(fun, geom):
return [not all([hasattr(y, "__iter__") for y in x]) and \
fun(*x) or apply_to_coord_pairs(fun, x) for x in geom]
return geoms.apply(trans)
Chacune de ces fonctions prend un code EPSG comme entrée pour les systèmes de référence de coordonnées d'origine et de destination. Les deux bibliothèques offrent des moyens alternatifs pour définir les informations de projection, mais les codes EPSG gardent le code assez simple pour l'instant.
Voici les résultats, en utilisant la %timeit
fonction magique dans ipython:
In [1]: %timeit transform_pyproj(l, 29903, 4326)
1 loops, best of 3: 641 ms per loop
In [2]: %timeit transform_osr(l, 29903, 4326)
10 loops, best of 3: 27.4 ms per loop
De toute évidence, la version «ogr.osr» est plus rapide, mais est-ce une comparaison équitable? La version «pyproj» se fait sur des points individuels et est principalement exécutée en Python, tandis que la version «ogr.osr» opère directement sur l'objet géométrique OGR. Y a-t-il une meilleure façon de comparer ces derniers?
projected_coords = numpy.vstack(pyproj.transform(origin, target, *numpy.array(geom).T)).T