0

I have a CSV file with records in below format.

area confidence boundary
159.1512 0.8084 POLYGON((87.7185491791352 22.5667828312016, 87.7184590804737 22.5667864311825, 87.7184519272495 22.5666320082646, 87.7185420258111 22.5666284082901, 87.7185491791352 22.5667828312016))

I am using the following python code which uses the boundary column to get the polygon shapefile from it.The code works fine however, when I add the exported the shapefile into ArcGIS the polygons are not falling on correct location.

import geopandas as gpd
import pandas as pd
from shapely.geometry import Polygon

df = pd.read_csv(r"/content/Test_Polygon.csv")

df.boundary = df.boundary.str.findall('\d+\.\d+').apply(lambda x: list(map(float, x))) #Extract numbers from boundary string

def givepoly(col):
    """Function to return a shapely polygon from a string of lat and longs"""
    return Polygon([[col[i+1], col[i]] for i in range(0, len(col)-1,2)])

df['geometry'] = df.apply(lambda row: givepoly(row['boundary']), axis=1)

df2 = gpd.GeoDataFrame(df, geometry='geometry', crs="EPSG:4326")
df2.drop('boundary', inplace=True, axis=1) #A shapefile cant have a list as data type
df2.to_file(r"/content/test3.shp")

enter image description here

Am not sure where am going wrong in this. I used the following link for reference : Converting CSV file with polygons in dictionary format into GeoDataFrame

8
  • You have a tag for ArcPy but the code that you've presented does use that module.
    – PolyGeo
    Feb 2 at 7:59
  • 1
    Traditionally the first thing to check is what coordinate order the library or application assumes - lon/lat or lat/lon.
    – user30184
    Feb 2 at 8:09
  • In this piece of code, it is assumed that the coordinates are referring to EPSG:4326 (WGS84). Are you sure this is the case with your coordinates?
    – kowalski
    Feb 2 at 8:10
  • The comment in the code "Function to return a shapely polygon from a string of lat and longs" but I believe that the geometry is lon-lats from around here openstreetmap.org/#map=5/22.567/87.719.
    – user30184
    Feb 2 at 8:37
  • @user30184 Yes, after your earlier I comment I paid attention to the order and indeed the file I have contains the order of Long/Lat whereas code is for Lat/Long order however, am not sure how to fix the code so that it takes Long/Lat order.
    – gis
    Feb 2 at 8:41

3 Answers 3

1

A better solution is to use directly geopandas.GeoSeries.from_wkt

 df = pd.read_csv("Test_Polygon.csv")
 print(df.boundary[0])
 POLYGON ((87.7185491791352 22.5667828312016, 87.7184590804737 22.5667864311825, 87.7184519272495 22.5666320082646, 87.7185420258111 22.5666284082901, 87.7185491791352 22.5667828312016))
 import geopandas as gpd
 s = gpd.GeoSeries.from_wkt(df.boundary)
 gdf = gpd.GeoDataFrame(data=df, geometry=s)
 print(gdf.geometry[0])
 POLYGON ((87.7185491791352 22.5667828312016, 87.7184590804737 22.5667864311825, 87.7184519272495 22.5666320082646, 87.7185420258111 22.5666284082901, 87.7185491791352 22.5667828312016))

You can also use shapely

from shapely import wkt
df["geom"] = gpd.GeoSeries.from_wkt(df["boundary"])
gdf2 = gpd.GeoDataFrame(df, geometry="geom")
print(gdf2.geometry[0])
POLYGON ((87.7185491791352 22.5667828312016, 87.7184590804737 22.5667864311825, 87.7184519272495 22.5666320082646, 87.7185420258111 22.5666284082901, 87.7185491791352 22.5667828312016))

or

df['geom2']= df.boundary.apply(wkt.loads)
gdf = gpd.GeoDataFrame(df, geometry='geom2')
print(gdf.geometry[0])
POLYGON ((87.7185491791352 22.5667828312016, 87.7184590804737 22.5667864311825, 87.7184519272495 22.5666320082646, 87.7185420258111 22.5666284082901, 87.7185491791352 22.5667828312016))
0
1

Swapping the values placed the geometry on correct location. Here's the modified the code:

import geopandas as gpd
import pandas as pd
from shapely.geometry import Polygon

df = pd.read_csv(r"/content/Test_Polygon.csv")

df.boundary = df.boundary.str.findall('\d+\.\d+').apply(lambda x: list(map(float, x))) #Extract numbers from boundary string

def givepoly(col):
    """Function to return a shapely polygon from a string of lat and longs"""
    return Polygon([[col[i], col[i + 1]] for i in range(0, len(col)-1,2)])

df['geometry'] = df.apply(lambda row: givepoly(row['boundary']), axis=1)

df2 = gpd.GeoDataFrame(df, geometry='geometry', crs="EPSG:4326")
df2.drop('boundary', inplace=True, axis=1) #A shapefile cant have a list as data type
df2.to_file(r"/content/test3.shp")

The only other concern that I have is when I add the shapefile to the map the geometries are displaying at a very small size.

enter image description here

Am not sure if this is an expected behaviour or code can be fixed so that geometry is displayed at an appropriate scale.

0

I tried adding the above mentioned code however got the error : TypeError: Expected bytes or string, got list


def givepoly(col):
    """Function to return a shapely polygon from a string of lat and longs"""
    return Polygon([[col[i], col[i+1]] for i in range(0, len(col)-1,2)])

df['geometry'] = df.apply(lambda row: givepoly(row['boundary']), axis=1)

s = gpd.GeoSeries.from_wkt(df.boundary)
df2 = gpd.GeoDataFrame(df, geometry=s)
df2.drop('boundary', inplace=True, axis=1) #A shapefile cant have a list as data type
df2.to_file(r"/content/test5.shp")

Not sure where am I going wrong.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.