For machine learning I need to convert array of coordinates in lon/lat format to simple floats where x=0,y=0 will be a most south/west coordinate and x=1,y=1 most north/east, and x=0.5,y=0.5 will be coordinate in a center.
What is a way to do this?
utm coordinates are suitable for your purposes, then note that in lieu of
utm package is now available and is simpler to use. Just be aware of
lat ordering vs.
northing ordering for the respective
to_latlon functions, per the docs.
The below conversion example would become:
import utm x, y = utm.from_latlon(input_lat, input_lon)
pyproj for converting your lng, lat pairs to a projected coordinate system. In other words you need to convert from your geographic coordinate system (most likely EPSG code 4326) to a local projected coordinate system, e.g. a local UTM zone or regional system such as the British National Grid (EPSG code 27700).
import pyproj as proj # setup your projections crs_wgs = proj.Proj(init='epsg:4326') # assuming you're using WGS84 geographic crs_bng = proj.Proj(init='epsg:27700') # use a locally appropriate projected CRS # then cast your geographic coordinate pair to the projected system x, y = proj.transform(crs_wgs, crs_bng, input_lon, input_lat)
pyproj.transform() also works on numpy arrays, so you can therefore transform your lon, lat arrays to x, y arrays. You can then use numpy's built-in array methods to normalise your values.
import numpy as np x = (x - x.min()) / (x.max() - x.min()) y = (y - y.min()) / (y.max() - y.min())
However, if you are using
sklearn already, then you may as well use sklearn.preprocessing.normalize.
It depends on what metric you need to preserve. One obvious approach is to project it to some appropriate flat coordinate system. To do this, you can use the
pyproj library. Then, simply rescale your coordinates to be in the range [0, 1]. However, this doesn't perfectly preserve spatial relationships because longitude and latitude are on a sphere (or an ellipsoid or geoid), and x,y coordinates are on a flat surface. You should read about different map projections to see what you may be losing. A good reference is Map Projections: A Working Manual. If your positions only cover a small patch of the Earth, the errors may be acceptable to you.
A second approach is to convert the longitude and latitude to (x, y, z) coordinates in 3d space. If you approximate the earth's surface as a sphere, then the formulae should be
x = sin(pi/2-lat) * cos(lon) y = sin(pi/2-lat) * sin(lon) z = cos(pi/2-lat)
lat are in radians. In this case however, z=-1 is the south pole, z=1 is the north pole, x=1 and x=-1 are the prime meridian, and the dateline, and y=1 and y=-1 are 90 degrees East and 90 degrees West. Again, you can rescale so that coordinates are [0,1] rather than [-1,1].
just use gdal.ApplyGeoTransform adn gdal.InvGeoTransform.Here's the python code:
src = gdal.Open(filename) #if the file contains GeoTransform geotrans = src.GetGeoTransform() #if the file contains only GCPs gcps = src.GetGCPs() geotrans = gdal.GCPsToGeoTransform(gcps) #from pixel coordinate to lat/lon lat, lon = gdal.ApplyGeoTransform(geoTrans, x,y) # from lat/lon to pixel coordinate invTs = gdal.InvGeoTransform(ts) x, y = gdal.ApplyGeoTransform(invTs, lat, lon)