# Interchange y, x to x, y with geopandas (python) or QGIS

I realized that the order of my geopandas dataframe is wrong, it has y, x instead of x, y.

This makes it difficult to use with other modules that needs exactly x, y type of coordinates. Is there any function in geopandas to interchange the coordinates without the need to enter in each geometry element, geometry type and change coordinates one by one? If not is there a shapely function to do it similarly instead of collecting all points one by one and change them?

More info: I have a geodataframe composed of a lineStrings (shapely object) in the geometry field for each row. If it's easier to do it in QGIS, I could also do it there.

• Where did you get your original dataframe? I would switch the coordinates as early in the workflow as possible, i.e. before you create a geodataframe.
– Jon
Commented Jul 31, 2018 at 18:39

`shapely.ops.transform` module allows passing a function to operate on coordinates. Therefore if you want to swap x, y coordinates in a GeoDataFrame you can use :

``````import shapely

gdf.geometry.map(lambda polygon: shapely.ops.transform(lambda x, y: (y, x), polygon))
``````

To account for 3D geometries (or as in my case, a mix of 2D and 3D), add the optional z=None parameter this way:

``````gdf.geometry.map(lambda myGeom: shapely.ops.transform(lambda x, y, z=None: (y, x, z), myGeom))
``````

BTW, this should work for all kinds of geometries (lines, points, polygons)

To swap (x,y) for any Shapely geometry type, here is a general function. It also preserves z coordinates (if present):

``````def swap_xy(geom):
if geom.is_empty:
return geom

if geom.has_z:
def swap_xy_coords(coords):
for x, y, z in coords:
yield (y, x, z)
else:
def swap_xy_coords(coords):
for x, y in coords:
yield (y, x)

# Process coordinates from each supported geometry type
if geom.type in ('Point', 'LineString', 'LinearRing'):
return type(geom)(list(swap_xy_coords(geom.coords)))
elif geom.type == 'Polygon':
ring = geom.exterior
shell = type(ring)(list(swap_xy_coords(ring.coords)))
holes = list(geom.interiors)
for pos, ring in enumerate(holes):
holes[pos] = type(ring)(list(swap_xy_coords(ring.coords)))
return type(geom)(shell, holes)
elif geom.type.startswith('Multi') or geom.type == 'GeometryCollection':
# Recursive call
return type(geom)([swap_xy(part) for part in geom.geoms])
else:
raise ValueError('Type %r not recognized' % geom.type)
``````

For example:

``````from shapely.geometry import Point, Polygon, MultiPoint, MultiLineString

# POINT Z (1 2 3) -> POINT Z (2 1 3)
swap_xy(Point(1, 2, 3))

# MULTILINESTRING ((1 2, 3 4)) -> MULTILINESTRING ((2 1, 4 3))
swap_xy(MultiLineString([[(1, 2), (3, 4)]]))

# Map the function to a geopandas geometry column
table.geometry = table.geometry.map(swap_xy)
``````
• While this is done well, it's probably safer / quicker / more general to use the `shapely.ops.transform` function as in the answer by MCMZL.
– Gijs
Commented Aug 8, 2019 at 9:37

It's easier to interchange coordinates by means of Swap XY plugin in QGIS. Just select the layer and click the button.

Changes are carried out in place so that you may need to backup.

QGIS 3.2 has a native "Swap X and Y coordinates" algorithm in the Processing Toolbox. This may come in handy if you need a GUI solution which works with all geometry types.

``````from shapely.geometry import Point, LineString
import geopandas

def swap(x):
coords = list(x.coords)
coords = [Point(t[1], t[0]) for t in coords] #Swap each coordinate using list comprehension and create Points
return LineString(coords)

df.geometry = df.geometry.map(swap) #Apply the function to the geometry of dataframe df
``````